blob: 7c08528f58a8d4f8b9346d412879de1c6cd1d78e [file] [log] [blame]
Pavel Kotucekd2c97d92017-01-24 10:58:12 +01001/*
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>
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +010027#include <vnet/classify/in_out_acl.h>
Pavel Kotucekd2c97d92017-01-24 10:58:12 +010028#include <vnet/classify/policer_classify.h>
29#include <vnet/classify/flow_classify.h>
Neale Rannsb8d44812017-11-10 06:53:54 -080030#include <vnet/l2/l2_classify.h>
Neale Rannse4031132020-10-26 13:00:06 +000031#include <vnet/ip/ip6.h>
32#include <vnet/ip/ip4.h>
Pavel Kotucekd2c97d92017-01-24 10:58:12 +010033
34#include <vnet/vnet_msg_enum.h>
35
36#define vl_typedefs /* define message structures */
37#include <vnet/vnet_all_api_h.h>
38#undef vl_typedefs
39
40#define vl_endianfun /* define message structures */
41#include <vnet/vnet_all_api_h.h>
42#undef vl_endianfun
43
44/* instantiate all the print functions we know about */
45#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
46#define vl_printfun
47#include <vnet/vnet_all_api_h.h>
48#undef vl_printfun
49
50#include <vlibapi/api_helper_macros.h>
51
52#define foreach_vpe_api_msg \
53_(CLASSIFY_ADD_DEL_TABLE, classify_add_del_table) \
54_(CLASSIFY_ADD_DEL_SESSION, classify_add_del_session) \
Jon Loeliger5c1e48c2020-10-15 14:41:36 -040055_(CLASSIFY_TABLE_IDS, classify_table_ids) \
Pavel Kotucekd2c97d92017-01-24 10:58:12 +010056_(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface) \
Jon Loeliger5c1e48c2020-10-15 14:41:36 -040057_(CLASSIFY_TABLE_INFO, classify_table_info) \
58_(CLASSIFY_SESSION_DUMP, classify_session_dump) \
Pavel Kotucekd2c97d92017-01-24 10:58:12 +010059_(POLICER_CLASSIFY_SET_INTERFACE, policer_classify_set_interface) \
60_(POLICER_CLASSIFY_DUMP, policer_classify_dump) \
61_(FLOW_CLASSIFY_SET_INTERFACE, flow_classify_set_interface) \
Neale Rannsb8d44812017-11-10 06:53:54 -080062_(FLOW_CLASSIFY_DUMP, flow_classify_dump) \
63_(INPUT_ACL_SET_INTERFACE, input_acl_set_interface) \
64_(CLASSIFY_SET_INTERFACE_IP_TABLE, classify_set_interface_ip_table) \
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +010065_(CLASSIFY_SET_INTERFACE_L2_TABLES, classify_set_interface_l2_tables) \
Jon Loeliger5c1e48c2020-10-15 14:41:36 -040066_(OUTPUT_ACL_SET_INTERFACE, output_acl_set_interface) \
67_(CLASSIFY_PCAP_LOOKUP_TABLE, classify_pcap_lookup_table) \
68_(CLASSIFY_PCAP_SET_TABLE, classify_pcap_set_table) \
69_(CLASSIFY_PCAP_GET_TABLES, classify_pcap_get_tables) \
70_(CLASSIFY_TRACE_LOOKUP_TABLE, classify_trace_lookup_table) \
71_(CLASSIFY_TRACE_SET_TABLE, classify_trace_set_table) \
72_(CLASSIFY_TRACE_GET_TABLES, classify_trace_get_tables) \
73
Pavel Kotucekd2c97d92017-01-24 10:58:12 +010074
75#define foreach_classify_add_del_table_field \
76_(table_index) \
77_(nbuckets) \
78_(memory_size) \
79_(skip_n_vectors) \
80_(match_n_vectors) \
81_(next_table_index) \
82_(miss_next_index) \
Juraj Sloboda75282452018-06-12 14:20:49 +020083_(mask_len)
Pavel Kotucekd2c97d92017-01-24 10:58:12 +010084
Jon Loeliger5c1e48c2020-10-15 14:41:36 -040085
86static void vl_api_classify_pcap_lookup_table_t_handler
87 (vl_api_classify_pcap_lookup_table_t * mp)
88{
89 vnet_classify_main_t *cm = &vnet_classify_main;
90 vl_api_registration_t *reg;
91 vl_api_classify_pcap_lookup_table_reply_t *rmp;
92 int rv = 0;
93 u32 table_index = ~0;
94
95 reg = vl_api_client_index_to_registration (mp->client_index);
96 if (!reg)
97 return;
98
99 u32 n_skip = ntohl (mp->skip_n_vectors);
100 u32 n_match = ntohl (mp->match_n_vectors);
101 u32 mask_len = ntohl (mp->mask_len);
102 u32 sw_if_index = ntohl (mp->sw_if_index);
103
Dave Barach99c6dc62021-02-15 12:46:47 -0500104 if (n_skip > 5 || n_match == 0 || n_match > 5 ||
105 mask_len != n_match * sizeof (u32x4) || sw_if_index == ~0 ||
106 sw_if_index >= vec_len (cm->classify_table_index_by_sw_if_index))
Jon Loeliger5c1e48c2020-10-15 14:41:36 -0400107 {
108 rv = VNET_API_ERROR_INVALID_VALUE;
109 goto out;
110 }
111
112 u32 table_chain;
113 table_chain = classify_get_pcap_chain (cm, sw_if_index);
114
115 u8 *mask_vec = 0;
116 vec_validate (mask_vec, mask_len - 1);
117 clib_memcpy (mask_vec, mp->mask, mask_len);
118
119 if (table_chain != ~0)
120 table_index = classify_lookup_chain (table_chain,
121 mask_vec, n_skip, n_match);
122
123 vec_free (mask_vec);
124
125out:
126 rmp = vl_msg_api_alloc (sizeof (*rmp));
127 rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_PCAP_LOOKUP_TABLE_REPLY);
128 rmp->context = mp->context;
129 rmp->retval = ntohl (rv);
130 rmp->table_index = htonl (table_index);
131
132 vl_api_send_msg (reg, (u8 *) rmp);
133}
134
135static void vl_api_classify_pcap_set_table_t_handler
136 (vl_api_classify_pcap_set_table_t * mp)
137{
138 vnet_classify_main_t *cm = &vnet_classify_main;
139 vl_api_classify_pcap_set_table_reply_t *rmp;
140 vl_api_registration_t *reg;
141 int rv = 0;
142
143 reg = vl_api_client_index_to_registration (mp->client_index);
144 if (!reg)
145 return;
146
147 u32 table_index = ntohl (mp->table_index);
148 u32 sw_if_index = ntohl (mp->sw_if_index);
149
150 if (sw_if_index == ~0
151 || sw_if_index >= vec_len (cm->classify_table_index_by_sw_if_index)
152 || (table_index != ~0 && pool_is_free_index (cm->tables, table_index)))
153 {
154 rv = VNET_API_ERROR_INVALID_VALUE;
155 goto out;
156 }
157
158 /*
159 * Maybe reorder tables such that masks are most-specify to least-specific.
160 */
161 if (table_index != ~0 && mp->sort_masks)
162 table_index = classify_sort_table_chain (cm, table_index);
163
164 classify_set_pcap_chain (cm, sw_if_index, table_index);
165
166out:
167 rmp = vl_msg_api_alloc (sizeof (*rmp));
168 rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_PCAP_SET_TABLE_REPLY);
169 rmp->context = mp->context;
170 rmp->retval = ntohl (rv);
171 rmp->table_index = htonl (table_index);
172
173 vl_api_send_msg (reg, (u8 *) rmp);
174}
175
176static void vl_api_classify_pcap_get_tables_t_handler
177 (vl_api_classify_pcap_get_tables_t * mp)
178{
179 vnet_classify_main_t *cm = &vnet_classify_main;
180 vl_api_classify_pcap_get_tables_reply_t *rmp;
181 vl_api_registration_t *reg;
182 int rv = 0;
183 u32 *tables = 0;
184 u32 count;
185
186 reg = vl_api_client_index_to_registration (mp->client_index);
187 if (!reg)
188 return;
189
190 u32 sw_if_index = ntohl (mp->sw_if_index);
191 if (sw_if_index == ~0
192 || sw_if_index >= vec_len (cm->classify_table_index_by_sw_if_index))
193 {
194 rv = VNET_API_ERROR_INVALID_VALUE;
195 goto out;
196 }
197
198 u32 table_index = classify_get_pcap_chain (cm, sw_if_index);
199 if (table_index == ~0)
200 goto out;
201
202 /*
203 * Form a vector of all classifier tables in this chain.
204 */
205 vnet_classify_table_t *t;
206 u32 i;
207
208 for (i = table_index; i != ~0; i = t->next_table_index)
209 {
210 vec_add1 (tables, i);
211 t = pool_elt_at_index (cm->tables, i);
212 }
213
214out:
215 count = vec_len (tables);
216 rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp) + count * sizeof (u32));
217 rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_PCAP_GET_TABLES_REPLY);
218 rmp->context = mp->context;
219 rmp->retval = ntohl (rv);
220 rmp->count = htonl (count);
221
222 for (i = 0; i < count; ++i)
223 {
224 rmp->indices[i] = htonl (tables[i]);
225 }
226
227 vec_free (tables);
228
229 vl_api_send_msg (reg, (u8 *) rmp);
230}
231
232
233static void vl_api_classify_trace_lookup_table_t_handler
234 (vl_api_classify_trace_lookup_table_t * mp)
235{
236 vl_api_classify_trace_lookup_table_reply_t *rmp;
237 vl_api_registration_t *reg;
238 int rv = 0;
239 u32 table_index = ~0;
240
241 reg = vl_api_client_index_to_registration (mp->client_index);
242 if (!reg)
243 return;
244
245 u32 n_skip = ntohl (mp->skip_n_vectors);
246 u32 n_match = ntohl (mp->match_n_vectors);
247 u32 mask_len = ntohl (mp->mask_len);
248 if (n_skip > 5
249 || n_match == 0 || n_match > 5 || mask_len != n_match * sizeof (u32x4))
250 {
251 rv = VNET_API_ERROR_INVALID_VALUE;
252 goto out;
253 }
254
255 u32 table_chain;
256 table_chain = classify_get_trace_chain ();
257
258 u8 *mask_vec = 0;
259 vec_validate (mask_vec, mask_len - 1);
260 clib_memcpy (mask_vec, mp->mask, mask_len);
261
262 if (table_chain != ~0)
263 table_index = classify_lookup_chain (table_chain,
264 mask_vec, n_skip, n_match);
265 vec_free (mask_vec);
266
267out:
268 rmp = vl_msg_api_alloc (sizeof (*rmp));
269 rmp->_vl_msg_id = ntohs ((VL_API_CLASSIFY_TRACE_LOOKUP_TABLE_REPLY));
270 rmp->context = mp->context;
271 rmp->retval = ntohl (rv);
272 rmp->table_index = htonl (table_index);
273
274 vl_api_send_msg (reg, (u8 *) rmp);
275}
276
277static void vl_api_classify_trace_set_table_t_handler
278 (vl_api_classify_trace_set_table_t * mp)
279{
280 vnet_classify_main_t *cm = &vnet_classify_main;
281 vl_api_classify_trace_set_table_reply_t *rmp;
282 vl_api_registration_t *reg;
283 int rv = 0;
284
285 reg = vl_api_client_index_to_registration (mp->client_index);
286 if (!reg)
287 return;
288
289 u32 table_index = ntohl (mp->table_index);
290 if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
291 {
292 rv = VNET_API_ERROR_INVALID_VALUE;
293 goto out;
294 }
295
296 /*
297 * Maybe reorder tables such that masks are most-specific to least-specific.
298 */
299 if (table_index != ~0 && mp->sort_masks)
300 table_index = classify_sort_table_chain (cm, table_index);
301
302 classify_set_trace_chain (cm, table_index);
303
304out:
305 rmp = vl_msg_api_alloc (sizeof (*rmp));
306 rmp->_vl_msg_id = ntohs ((VL_API_CLASSIFY_TRACE_SET_TABLE_REPLY));
307 rmp->context = mp->context;
308 rmp->retval = ntohl (rv);
309 rmp->table_index = htonl (table_index);
310
311 vl_api_send_msg (reg, (u8 *) rmp);
312}
313
314static void vl_api_classify_trace_get_tables_t_handler
315 (vl_api_classify_trace_get_tables_t * mp)
316{
317 vnet_classify_main_t *cm = &vnet_classify_main;
318 vl_api_classify_trace_get_tables_reply_t *rmp;
319 vl_api_registration_t *reg;
320 int rv = 0;
321 u32 *tables = 0;
322 u32 count;
323
324 reg = vl_api_client_index_to_registration (mp->client_index);
325 if (!reg)
326 return;
327
328 u32 table_index = classify_get_trace_chain ();
329 if (table_index == ~0)
330 goto out;
331
332 /*
333 * Form a vector of all classifier tables in this chain.
334 */
335 vnet_classify_table_t *t;
336 u32 i;
337
338 for (i = table_index; i != ~0; i = t->next_table_index)
339 {
340 vec_add1 (tables, i);
341 t = pool_elt_at_index (cm->tables, i);
342 }
343
344out:
345 count = vec_len (tables);
346 rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp) + count * sizeof (u32));
347 rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TRACE_GET_TABLES_REPLY);
348 rmp->context = mp->context;
349 rmp->retval = ntohl (rv);
350 rmp->count = htonl (count);
351
352 for (i = 0; i < count; ++i)
353 {
354 rmp->indices[i] = htonl (tables[i]);
355 }
356
357 vec_free (tables);
358
359 vl_api_send_msg (reg, (u8 *) rmp);
360}
361
362
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100363static void vl_api_classify_add_del_table_t_handler
364 (vl_api_classify_add_del_table_t * mp)
365{
366 vl_api_classify_add_del_table_reply_t *rmp;
367 vnet_classify_main_t *cm = &vnet_classify_main;
368 vnet_classify_table_t *t;
369 int rv;
370
371#define _(a) u32 a;
372 foreach_classify_add_del_table_field;
373#undef _
374
375#define _(a) a = ntohl(mp->a);
376 foreach_classify_add_del_table_field;
377#undef _
378
Juraj Sloboda75282452018-06-12 14:20:49 +0200379 if (mask_len != match_n_vectors * sizeof (u32x4))
380 {
381 rv = VNET_API_ERROR_INVALID_VALUE;
382 goto out;
383 }
384
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100385 /* The underlying API fails silently, on purpose, so check here */
386 if (mp->is_add == 0) /* delete */
387 {
388 if (pool_is_free_index (cm->tables, table_index))
389 {
390 rv = VNET_API_ERROR_NO_SUCH_TABLE;
391 goto out;
392 }
393 }
394 else /* add or update */
395 {
396 if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
397 table_index = ~0;
398 }
399
Jakub Grajciar692bfc82019-08-27 10:16:44 +0200400 u8 current_data_flag = mp->current_data_flag;
401 i16 current_data_offset = clib_net_to_host_i16 (mp->current_data_offset);
402
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100403 rv = vnet_classify_add_del_table
404 (cm, mp->mask, nbuckets, memory_size,
405 skip_n_vectors, match_n_vectors,
406 next_table_index, miss_next_index, &table_index,
407 current_data_flag, current_data_offset, mp->is_add, mp->del_chain);
408
409out:
410 /* *INDENT-OFF* */
411 REPLY_MACRO2(VL_API_CLASSIFY_ADD_DEL_TABLE_REPLY,
412 ({
413 if (rv == 0 && mp->is_add)
414 {
415 t = pool_elt_at_index (cm->tables, table_index);
Jakub Grajciar692bfc82019-08-27 10:16:44 +0200416 rmp->skip_n_vectors = htonl(t->skip_n_vectors);
417 rmp->match_n_vectors = htonl(t->match_n_vectors);
418 rmp->new_table_index = htonl(table_index);
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100419 }
420 else
421 {
422 rmp->skip_n_vectors = ~0;
423 rmp->match_n_vectors = ~0;
424 rmp->new_table_index = ~0;
425 }
426 }));
427 /* *INDENT-ON* */
428}
429
430static void vl_api_classify_add_del_session_t_handler
431 (vl_api_classify_add_del_session_t * mp)
432{
433 vnet_classify_main_t *cm = &vnet_classify_main;
434 vl_api_classify_add_del_session_reply_t *rmp;
435 int rv;
Juraj Sloboda75282452018-06-12 14:20:49 +0200436 u32 table_index, hit_next_index, opaque_index, metadata, match_len;
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100437 i32 advance;
438 u8 action;
Juraj Sloboda75282452018-06-12 14:20:49 +0200439 vnet_classify_table_t *t;
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100440
441 table_index = ntohl (mp->table_index);
442 hit_next_index = ntohl (mp->hit_next_index);
443 opaque_index = ntohl (mp->opaque_index);
444 advance = ntohl (mp->advance);
445 action = mp->action;
446 metadata = ntohl (mp->metadata);
Juraj Sloboda75282452018-06-12 14:20:49 +0200447 match_len = ntohl (mp->match_len);
448
449 if (pool_is_free_index (cm->tables, table_index))
450 {
451 rv = VNET_API_ERROR_NO_SUCH_TABLE;
452 goto out;
453 }
454
455 t = pool_elt_at_index (cm->tables, table_index);
456
457 if (match_len != (t->skip_n_vectors + t->match_n_vectors) * sizeof (u32x4))
458 {
459 rv = VNET_API_ERROR_INVALID_VALUE;
460 goto out;
461 }
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100462
463 rv = vnet_classify_add_del_session
464 (cm, table_index, mp->match, hit_next_index, opaque_index,
465 advance, action, metadata, mp->is_add);
466
Juraj Sloboda75282452018-06-12 14:20:49 +0200467out:
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100468 REPLY_MACRO (VL_API_CLASSIFY_ADD_DEL_SESSION_REPLY);
469}
470
471static void
472 vl_api_policer_classify_set_interface_t_handler
473 (vl_api_policer_classify_set_interface_t * mp)
474{
475 vlib_main_t *vm = vlib_get_main ();
476 vl_api_policer_classify_set_interface_reply_t *rmp;
477 int rv;
478 u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
479
480 ip4_table_index = ntohl (mp->ip4_table_index);
481 ip6_table_index = ntohl (mp->ip6_table_index);
482 l2_table_index = ntohl (mp->l2_table_index);
483 sw_if_index = ntohl (mp->sw_if_index);
484
485 VALIDATE_SW_IF_INDEX (mp);
486
487 rv = vnet_set_policer_classify_intfc (vm, sw_if_index, ip4_table_index,
488 ip6_table_index, l2_table_index,
489 mp->is_add);
490
491 BAD_SW_IF_INDEX_LABEL;
492
493 REPLY_MACRO (VL_API_POLICER_CLASSIFY_SET_INTERFACE_REPLY);
494}
495
496static void
497send_policer_classify_details (u32 sw_if_index,
Florin Coras6c4dae22018-01-09 06:39:23 -0800498 u32 table_index, vl_api_registration_t * reg,
499 u32 context)
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100500{
501 vl_api_policer_classify_details_t *mp;
502
503 mp = vl_msg_api_alloc (sizeof (*mp));
Dave Barachb7b92992018-10-17 10:38:51 -0400504 clib_memset (mp, 0, sizeof (*mp));
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100505 mp->_vl_msg_id = ntohs (VL_API_POLICER_CLASSIFY_DETAILS);
506 mp->context = context;
507 mp->sw_if_index = htonl (sw_if_index);
508 mp->table_index = htonl (table_index);
509
Florin Coras6c4dae22018-01-09 06:39:23 -0800510 vl_api_send_msg (reg, (u8 *) mp);
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100511}
512
513static void
514vl_api_policer_classify_dump_t_handler (vl_api_policer_classify_dump_t * mp)
515{
Florin Coras6c4dae22018-01-09 06:39:23 -0800516 vl_api_registration_t *reg;
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100517 policer_classify_main_t *pcm = &policer_classify_main;
518 u32 *vec_tbl;
519 int i;
Jakub Grajciar692bfc82019-08-27 10:16:44 +0200520 u32 filter_sw_if_index;
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100521
Florin Coras6c4dae22018-01-09 06:39:23 -0800522 reg = vl_api_client_index_to_registration (mp->client_index);
523 if (!reg)
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100524 return;
525
Jakub Grajciar692bfc82019-08-27 10:16:44 +0200526 filter_sw_if_index = ntohl (mp->sw_if_index);
Jon Loeliger95d2f302019-12-04 11:42:36 -0600527 if (filter_sw_if_index
528 >= vec_len (pcm->classify_table_index_by_sw_if_index[mp->type]))
529 return;
530
Jakub Grajciar692bfc82019-08-27 10:16:44 +0200531 if (filter_sw_if_index != ~0)
532 vec_tbl =
533 &pcm->classify_table_index_by_sw_if_index[mp->type][filter_sw_if_index];
534 else
535 vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100536
537 if (vec_len (vec_tbl))
538 {
539 for (i = 0; i < vec_len (vec_tbl); i++)
540 {
541 if (vec_elt (vec_tbl, i) == ~0)
542 continue;
543
Florin Coras6c4dae22018-01-09 06:39:23 -0800544 send_policer_classify_details (i, vec_elt (vec_tbl, i), reg,
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100545 mp->context);
546 }
547 }
548}
549
550static void
551vl_api_classify_table_ids_t_handler (vl_api_classify_table_ids_t * mp)
552{
Florin Coras6c4dae22018-01-09 06:39:23 -0800553 vl_api_registration_t *reg;
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100554
Florin Coras6c4dae22018-01-09 06:39:23 -0800555 reg = vl_api_client_index_to_registration (mp->client_index);
556 if (!reg)
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100557 return;
558
559 vnet_classify_main_t *cm = &vnet_classify_main;
560 vnet_classify_table_t *t;
561 u32 *table_ids = 0;
562 u32 count;
563
564 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100565 pool_foreach (t, cm->tables)
566 {
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100567 vec_add1 (table_ids, ntohl(t - cm->tables));
Damjan Marionb2c31b62020-12-13 21:47:40 +0100568 }
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100569 /* *INDENT-ON* */
570 count = vec_len (table_ids);
571
572 vl_api_classify_table_ids_reply_t *rmp;
573 rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp) + count * sizeof (u32));
574 rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_IDS_REPLY);
575 rmp->context = mp->context;
576 rmp->count = ntohl (count);
577 clib_memcpy (rmp->ids, table_ids, count * sizeof (u32));
578 rmp->retval = 0;
579
Florin Coras6c4dae22018-01-09 06:39:23 -0800580 vl_api_send_msg (reg, (u8 *) rmp);
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100581
582 vec_free (table_ids);
583}
584
585static void
586 vl_api_classify_table_by_interface_t_handler
587 (vl_api_classify_table_by_interface_t * mp)
588{
589 vl_api_classify_table_by_interface_reply_t *rmp;
590 int rv = 0;
591
592 u32 sw_if_index = ntohl (mp->sw_if_index);
593 u32 *acl = 0;
594
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +0100595 vec_validate (acl, IN_OUT_ACL_N_TABLES - 1);
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100596 vec_set (acl, ~0);
597
598 VALIDATE_SW_IF_INDEX (mp);
599
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +0100600 in_out_acl_main_t *am = &in_out_acl_main;
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100601
602 int if_idx;
603 u32 type;
604
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +0100605 for (type = 0; type < IN_OUT_ACL_N_TABLES; type++)
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100606 {
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +0100607 u32 *vec_tbl =
608 am->classify_table_index_by_sw_if_index[IN_OUT_ACL_INPUT_TABLE_GROUP]
609 [type];
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100610 if (vec_len (vec_tbl))
611 {
612 for (if_idx = 0; if_idx < vec_len (vec_tbl); if_idx++)
613 {
614 if (vec_elt (vec_tbl, if_idx) == ~0 || sw_if_index != if_idx)
615 {
616 continue;
617 }
618 acl[type] = vec_elt (vec_tbl, if_idx);
619 }
620 }
621 }
622
623 BAD_SW_IF_INDEX_LABEL;
624
625 /* *INDENT-OFF* */
626 REPLY_MACRO2(VL_API_CLASSIFY_TABLE_BY_INTERFACE_REPLY,
627 ({
628 rmp->sw_if_index = ntohl(sw_if_index);
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +0100629 rmp->l2_table_id = ntohl(acl[IN_OUT_ACL_TABLE_L2]);
630 rmp->ip4_table_id = ntohl(acl[IN_OUT_ACL_TABLE_IP4]);
631 rmp->ip6_table_id = ntohl(acl[IN_OUT_ACL_TABLE_IP6]);
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100632 }));
633 /* *INDENT-ON* */
634 vec_free (acl);
635}
636
637static void
638vl_api_classify_table_info_t_handler (vl_api_classify_table_info_t * mp)
639{
Florin Coras6c4dae22018-01-09 06:39:23 -0800640 vl_api_registration_t *reg;
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100641
Florin Coras6c4dae22018-01-09 06:39:23 -0800642 reg = vl_api_client_index_to_registration (mp->client_index);
643 if (!reg)
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100644 return;
645
646 vl_api_classify_table_info_reply_t *rmp = 0;
647
648 vnet_classify_main_t *cm = &vnet_classify_main;
649 u32 table_id = ntohl (mp->table_id);
650 vnet_classify_table_t *t;
651
652 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100653 pool_foreach (t, cm->tables)
654 {
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100655 if (table_id == t - cm->tables)
656 {
657 rmp = vl_msg_api_alloc_as_if_client
658 (sizeof (*rmp) + t->match_n_vectors * sizeof (u32x4));
659 rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_INFO_REPLY);
660 rmp->context = mp->context;
661 rmp->table_id = ntohl(table_id);
662 rmp->nbuckets = ntohl(t->nbuckets);
663 rmp->match_n_vectors = ntohl(t->match_n_vectors);
664 rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
665 rmp->active_sessions = ntohl(t->active_elements);
666 rmp->next_table_index = ntohl(t->next_table_index);
667 rmp->miss_next_index = ntohl(t->miss_next_index);
668 rmp->mask_length = ntohl(t->match_n_vectors * sizeof (u32x4));
669 clib_memcpy(rmp->mask, t->mask, t->match_n_vectors * sizeof(u32x4));
670 rmp->retval = 0;
671 break;
672 }
Damjan Marionb2c31b62020-12-13 21:47:40 +0100673 }
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100674 /* *INDENT-ON* */
675
676 if (rmp == 0)
677 {
678 rmp = vl_msg_api_alloc (sizeof (*rmp));
Jon Loeliger5c1e48c2020-10-15 14:41:36 -0400679 rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_INFO_REPLY);
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100680 rmp->context = mp->context;
681 rmp->retval = ntohl (VNET_API_ERROR_CLASSIFY_TABLE_NOT_FOUND);
682 }
683
Florin Coras6c4dae22018-01-09 06:39:23 -0800684 vl_api_send_msg (reg, (u8 *) rmp);
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100685}
686
687static void
Florin Coras6c4dae22018-01-09 06:39:23 -0800688send_classify_session_details (vl_api_registration_t * reg,
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100689 u32 table_id,
690 u32 match_length,
691 vnet_classify_entry_t * e, u32 context)
692{
693 vl_api_classify_session_details_t *rmp;
694
695 rmp = vl_msg_api_alloc (sizeof (*rmp));
Dave Barachb7b92992018-10-17 10:38:51 -0400696 clib_memset (rmp, 0, sizeof (*rmp));
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100697 rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_SESSION_DETAILS);
698 rmp->context = context;
699 rmp->table_id = ntohl (table_id);
700 rmp->hit_next_index = ntohl (e->next_index);
701 rmp->advance = ntohl (e->advance);
702 rmp->opaque_index = ntohl (e->opaque_index);
703 rmp->match_length = ntohl (match_length);
704 clib_memcpy (rmp->match, e->key, match_length);
705
Florin Coras6c4dae22018-01-09 06:39:23 -0800706 vl_api_send_msg (reg, (u8 *) rmp);
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100707}
708
709static void
710vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t * mp)
711{
712 vnet_classify_main_t *cm = &vnet_classify_main;
Florin Coras6c4dae22018-01-09 06:39:23 -0800713 vl_api_registration_t *reg;
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100714
715 u32 table_id = ntohl (mp->table_id);
716 vnet_classify_table_t *t;
717
Florin Coras6c4dae22018-01-09 06:39:23 -0800718 reg = vl_api_client_index_to_registration (mp->client_index);
719 if (!reg)
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100720 return;
721
722 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100723 pool_foreach (t, cm->tables)
724 {
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100725 if (table_id == t - cm->tables)
726 {
727 vnet_classify_bucket_t * b;
728 vnet_classify_entry_t * v, * save_v;
729 int i, j, k;
730
731 for (i = 0; i < t->nbuckets; i++)
732 {
733 b = &t->buckets [i];
734 if (b->offset == 0)
735 continue;
736
737 save_v = vnet_classify_get_entry (t, b->offset);
738 for (j = 0; j < (1<<b->log2_pages); j++)
739 {
740 for (k = 0; k < t->entries_per_page; k++)
741 {
742 v = vnet_classify_entry_at_index
743 (t, save_v, j*t->entries_per_page + k);
744 if (vnet_classify_entry_is_free (v))
745 continue;
746
747 send_classify_session_details
Florin Coras6c4dae22018-01-09 06:39:23 -0800748 (reg, table_id, t->match_n_vectors * sizeof (u32x4),
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100749 v, mp->context);
750 }
751 }
752 }
753 break;
754 }
Damjan Marionb2c31b62020-12-13 21:47:40 +0100755 }
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100756 /* *INDENT-ON* */
757}
758
759static void
760 vl_api_flow_classify_set_interface_t_handler
761 (vl_api_flow_classify_set_interface_t * mp)
762{
763 vlib_main_t *vm = vlib_get_main ();
764 vl_api_flow_classify_set_interface_reply_t *rmp;
765 int rv;
766 u32 sw_if_index, ip4_table_index, ip6_table_index;
767
768 ip4_table_index = ntohl (mp->ip4_table_index);
769 ip6_table_index = ntohl (mp->ip6_table_index);
770 sw_if_index = ntohl (mp->sw_if_index);
771
772 VALIDATE_SW_IF_INDEX (mp);
773
774 rv = vnet_set_flow_classify_intfc (vm, sw_if_index, ip4_table_index,
775 ip6_table_index, mp->is_add);
776
777 BAD_SW_IF_INDEX_LABEL;
778
779 REPLY_MACRO (VL_API_FLOW_CLASSIFY_SET_INTERFACE_REPLY);
780}
781
782static void
783send_flow_classify_details (u32 sw_if_index,
Florin Coras6c4dae22018-01-09 06:39:23 -0800784 u32 table_index, vl_api_registration_t * reg,
785 u32 context)
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100786{
787 vl_api_flow_classify_details_t *mp;
788
789 mp = vl_msg_api_alloc (sizeof (*mp));
Dave Barachb7b92992018-10-17 10:38:51 -0400790 clib_memset (mp, 0, sizeof (*mp));
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100791 mp->_vl_msg_id = ntohs (VL_API_FLOW_CLASSIFY_DETAILS);
792 mp->context = context;
793 mp->sw_if_index = htonl (sw_if_index);
794 mp->table_index = htonl (table_index);
795
Florin Coras6c4dae22018-01-09 06:39:23 -0800796 vl_api_send_msg (reg, (u8 *) mp);
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100797}
798
799static void
800vl_api_flow_classify_dump_t_handler (vl_api_flow_classify_dump_t * mp)
801{
Florin Coras6c4dae22018-01-09 06:39:23 -0800802 vl_api_registration_t *reg;
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100803 flow_classify_main_t *pcm = &flow_classify_main;
804 u32 *vec_tbl;
805 int i;
Jakub Grajciar692bfc82019-08-27 10:16:44 +0200806 u32 filter_sw_if_index;
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100807
Florin Coras6c4dae22018-01-09 06:39:23 -0800808 reg = vl_api_client_index_to_registration (mp->client_index);
809 if (!reg)
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100810 return;
811
Jakub Grajciar692bfc82019-08-27 10:16:44 +0200812 filter_sw_if_index = ntohl (mp->sw_if_index);
Jon Loeliger95d2f302019-12-04 11:42:36 -0600813 if (filter_sw_if_index
814 >= vec_len (pcm->classify_table_index_by_sw_if_index[mp->type]))
815 return;
816
Jakub Grajciar692bfc82019-08-27 10:16:44 +0200817 if (filter_sw_if_index != ~0)
818 vec_tbl =
819 &pcm->classify_table_index_by_sw_if_index[mp->type][filter_sw_if_index];
820 else
821 vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100822
823 if (vec_len (vec_tbl))
824 {
825 for (i = 0; i < vec_len (vec_tbl); i++)
826 {
827 if (vec_elt (vec_tbl, i) == ~0)
828 continue;
829
Florin Coras6c4dae22018-01-09 06:39:23 -0800830 send_flow_classify_details (i, vec_elt (vec_tbl, i), reg,
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100831 mp->context);
832 }
833 }
834}
835
Neale Rannsb8d44812017-11-10 06:53:54 -0800836static void vl_api_classify_set_interface_ip_table_t_handler
837 (vl_api_classify_set_interface_ip_table_t * mp)
838{
839 vlib_main_t *vm = vlib_get_main ();
840 vl_api_classify_set_interface_ip_table_reply_t *rmp;
841 int rv;
842
843 VALIDATE_SW_IF_INDEX (mp);
844
845 u32 table_index = ntohl (mp->table_index);
846 u32 sw_if_index = ntohl (mp->sw_if_index);
847
848 if (mp->is_ipv6)
849 rv = vnet_set_ip6_classify_intfc (vm, sw_if_index, table_index);
850 else
851 rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
852
853 BAD_SW_IF_INDEX_LABEL;
854
855 REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY);
856}
857
858static void vl_api_classify_set_interface_l2_tables_t_handler
859 (vl_api_classify_set_interface_l2_tables_t * mp)
860{
861 vl_api_classify_set_interface_l2_tables_reply_t *rmp;
862 int rv;
863 u32 sw_if_index, ip4_table_index, ip6_table_index, other_table_index;
864 int enable;
865
866 ip4_table_index = ntohl (mp->ip4_table_index);
867 ip6_table_index = ntohl (mp->ip6_table_index);
868 other_table_index = ntohl (mp->other_table_index);
869 sw_if_index = ntohl (mp->sw_if_index);
870
871 VALIDATE_SW_IF_INDEX (mp);
872
873 if (mp->is_input)
874 rv = vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index,
875 ip6_table_index,
876 other_table_index);
877 else
878 rv = vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index,
879 ip6_table_index,
880 other_table_index);
881
882 if (rv == 0)
883 {
884 if (ip4_table_index != ~0 || ip6_table_index != ~0
885 || other_table_index != ~0)
886 enable = 1;
887 else
888 enable = 0;
889
890 if (mp->is_input)
891 vnet_l2_input_classify_enable_disable (sw_if_index, enable);
892 else
893 vnet_l2_output_classify_enable_disable (sw_if_index, enable);
894 }
895
896 BAD_SW_IF_INDEX_LABEL;
897
898 REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY);
899}
900
901static void vl_api_input_acl_set_interface_t_handler
902 (vl_api_input_acl_set_interface_t * mp)
903{
904 vlib_main_t *vm = vlib_get_main ();
905 vl_api_input_acl_set_interface_reply_t *rmp;
906 int rv;
907
908 VALIDATE_SW_IF_INDEX (mp);
909
910 u32 ip4_table_index = ntohl (mp->ip4_table_index);
911 u32 ip6_table_index = ntohl (mp->ip6_table_index);
912 u32 l2_table_index = ntohl (mp->l2_table_index);
913 u32 sw_if_index = ntohl (mp->sw_if_index);
914
915 rv = vnet_set_input_acl_intfc (vm, sw_if_index, ip4_table_index,
916 ip6_table_index, l2_table_index, mp->is_add);
917
918 BAD_SW_IF_INDEX_LABEL;
919
920 REPLY_MACRO (VL_API_INPUT_ACL_SET_INTERFACE_REPLY);
921}
922
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +0100923static void vl_api_output_acl_set_interface_t_handler
924 (vl_api_output_acl_set_interface_t * mp)
925{
926 vlib_main_t *vm = vlib_get_main ();
927 vl_api_output_acl_set_interface_reply_t *rmp;
928 int rv;
929
930 VALIDATE_SW_IF_INDEX (mp);
931
932 u32 ip4_table_index = ntohl (mp->ip4_table_index);
933 u32 ip6_table_index = ntohl (mp->ip6_table_index);
934 u32 l2_table_index = ntohl (mp->l2_table_index);
935 u32 sw_if_index = ntohl (mp->sw_if_index);
936
937 rv = vnet_set_output_acl_intfc (vm, sw_if_index, ip4_table_index,
938 ip6_table_index, l2_table_index,
939 mp->is_add);
940
941 BAD_SW_IF_INDEX_LABEL;
942
943 REPLY_MACRO (VL_API_OUTPUT_ACL_SET_INTERFACE_REPLY);
944}
945
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100946/*
947 * classify_api_hookup
948 * Add vpe's API message handlers to the table.
Jim Thompsonf324dec2019-04-08 03:22:21 -0500949 * vlib has already mapped shared memory and
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100950 * added the client registration handlers.
951 * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
952 */
953#define vl_msg_name_crc_list
954#include <vnet/vnet_all_api_h.h>
955#undef vl_msg_name_crc_list
956
957static void
958setup_message_id_table (api_main_t * am)
959{
960#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
961 foreach_vl_msg_name_crc_classify;
962#undef _
963}
964
965static clib_error_t *
966classify_api_hookup (vlib_main_t * vm)
967{
Dave Barach39d69112019-11-27 11:42:13 -0500968 api_main_t *am = vlibapi_get_main ();
Pavel Kotucekd2c97d92017-01-24 10:58:12 +0100969
970#define _(N,n) \
971 vl_msg_api_set_handlers(VL_API_##N, #n, \
972 vl_api_##n##_t_handler, \
973 vl_noop_handler, \
974 vl_api_##n##_t_endian, \
975 vl_api_##n##_t_print, \
976 sizeof(vl_api_##n##_t), 1);
977 foreach_vpe_api_msg;
978#undef _
979
980 /*
981 * Set up the (msg_name, crc, message-id) table
982 */
983 setup_message_id_table (am);
984
985 return 0;
986}
987
988VLIB_API_INIT_FUNCTION (classify_api_hookup);
989
990/*
991 * fd.io coding-style-patch-verification: ON
992 *
993 * Local Variables:
994 * eval: (c-set-style "gnu")
995 * End:
996 */