FD.io VPP  v17.10-9-gd594711
Vector Packet Processing
acl.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <stddef.h>
17 
18 #include <vnet/vnet.h>
19 #include <vnet/plugin/plugin.h>
20 #include <acl/acl.h>
21 
22 #include <vnet/l2/l2_classify.h>
24 #include <vpp/app/version.h>
25 
26 #include <vlibapi/api.h>
27 #include <vlibmemory/api.h>
28 #include <vlibsocket/api.h>
29 
30 /* define message IDs */
31 #include <acl/acl_msg_enum.h>
32 
33 /* define message structures */
34 #define vl_typedefs
35 #include <acl/acl_all_api_h.h>
36 #undef vl_typedefs
37 
38 /* define generated endian-swappers */
39 #define vl_endianfun
40 #include <acl/acl_all_api_h.h>
41 #undef vl_endianfun
42 
43 /* instantiate all the print functions we know about */
44 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
45 #define vl_printfun
46 #include <acl/acl_all_api_h.h>
47 #undef vl_printfun
48 
49 /* Get the API version number */
50 #define vl_api_version(n,v) static u32 api_version=(v);
51 #include <acl/acl_all_api_h.h>
52 #undef vl_api_version
53 
54 #include "fa_node.h"
55 #include "hash_lookup.h"
56 
58 
59 #define REPLY_MSG_ID_BASE am->msg_id_base
61 
62 /* List of message types that this plugin understands */
63 
64 #define foreach_acl_plugin_api_msg \
65 _(ACL_PLUGIN_GET_VERSION, acl_plugin_get_version) \
66 _(ACL_PLUGIN_CONTROL_PING, acl_plugin_control_ping) \
67 _(ACL_ADD_REPLACE, acl_add_replace) \
68 _(ACL_DEL, acl_del) \
69 _(ACL_INTERFACE_ADD_DEL, acl_interface_add_del) \
70 _(ACL_INTERFACE_SET_ACL_LIST, acl_interface_set_acl_list) \
71 _(ACL_DUMP, acl_dump) \
72 _(ACL_INTERFACE_LIST_DUMP, acl_interface_list_dump) \
73 _(MACIP_ACL_ADD, macip_acl_add) \
74 _(MACIP_ACL_ADD_REPLACE, macip_acl_add_replace) \
75 _(MACIP_ACL_DEL, macip_acl_del) \
76 _(MACIP_ACL_INTERFACE_ADD_DEL, macip_acl_interface_add_del) \
77 _(MACIP_ACL_DUMP, macip_acl_dump) \
78 _(MACIP_ACL_INTERFACE_GET, macip_acl_interface_get) \
79 _(MACIP_ACL_INTERFACE_LIST_DUMP, macip_acl_interface_list_dump)
80 
81 
82 /* *INDENT-OFF* */
84  .version = VPP_BUILD_VER,
85  .description = "Access Control Lists",
86 };
87 /* *INDENT-ON* */
88 
89 
90 static void *
92 {
93  if (0 == am->acl_mheap) {
94  am->acl_mheap = mheap_alloc (0 /* use VM */ , am->acl_mheap_size);
97  }
98  void *oldheap = clib_mem_set_heap(am->acl_mheap);
99  return oldheap;
100 }
101 
102 void
104 {
106  mheap_t *h = mheap_header (am->acl_mheap);
107  if (on) {
110  mheap_validate(h);
111  } else {
112  h->flags &= ~MHEAP_FLAG_VALIDATE;
114  }
115 }
116 
117 void
119 {
121  mheap_t *h = mheap_header (am->acl_mheap);
122  if (on) {
123  h->flags |= MHEAP_FLAG_TRACE;
124  } else {
125  h->flags &= ~MHEAP_FLAG_TRACE;
126  }
127 }
128 
129 static void
131 {
132  acl_main_t *am = &acl_main;
134  int msg_size = sizeof (*rmp);
136 
138  if (q == 0)
139  {
140  return;
141  }
142 
143  rmp = vl_msg_api_alloc (msg_size);
144  memset (rmp, 0, msg_size);
145  rmp->_vl_msg_id =
146  ntohs (VL_API_ACL_PLUGIN_GET_VERSION_REPLY + am->msg_id_base);
147  rmp->context = mp->context;
148  rmp->major = htonl (ACL_PLUGIN_VERSION_MAJOR);
149  rmp->minor = htonl (ACL_PLUGIN_VERSION_MINOR);
150 
151  vl_msg_api_send_shmem (q, (u8 *) & rmp);
152 }
153 
154 static void
156 {
158  acl_main_t *am = &acl_main;
159  int rv = 0;
160 
161  /* *INDENT-OFF* */
162  REPLY_MACRO2 (VL_API_ACL_PLUGIN_CONTROL_PING_REPLY,
163  ({
164  rmp->vpe_pid = ntohl (getpid ());
165  }));
166  /* *INDENT-ON* */
167 }
168 
169 static int
171  u32 * acl_list_index, u8 * tag)
172 {
173  acl_main_t *am = &acl_main;
174  acl_list_t *a;
175  acl_rule_t *r;
176  acl_rule_t *acl_new_rules = 0;
177  int i;
178 
179  if (*acl_list_index != ~0)
180  {
181  /* They supplied some number, let's see if this ACL exists */
182  if (pool_is_free_index (am->acls, *acl_list_index))
183  {
184  /* tried to replace a non-existent ACL, no point doing anything */
185  clib_warning("acl-plugin-error: Trying to replace nonexistent ACL %d (tag %s)", *acl_list_index, tag);
186  return -1;
187  }
188  }
189  if (0 == count) {
190  clib_warning("acl-plugin-warning: supplied no rules for ACL %d (tag %s)", *acl_list_index, tag);
191  }
192 
193  void *oldheap = acl_set_heap(am);
194 
195  /* Create and populate the rules */
196  if (count > 0)
197  vec_validate(acl_new_rules, count-1);
198 
199  for (i = 0; i < count; i++)
200  {
201  r = vec_elt_at_index(acl_new_rules, i);
202  memset(r, 0, sizeof(*r));
203  r->is_permit = rules[i].is_permit;
204  r->is_ipv6 = rules[i].is_ipv6;
205  if (r->is_ipv6)
206  {
207  memcpy (&r->src, rules[i].src_ip_addr, sizeof (r->src));
208  memcpy (&r->dst, rules[i].dst_ip_addr, sizeof (r->dst));
209  }
210  else
211  {
212  memcpy (&r->src.ip4, rules[i].src_ip_addr, sizeof (r->src.ip4));
213  memcpy (&r->dst.ip4, rules[i].dst_ip_addr, sizeof (r->dst.ip4));
214  }
215  r->src_prefixlen = rules[i].src_ip_prefix_len;
216  r->dst_prefixlen = rules[i].dst_ip_prefix_len;
217  r->proto = rules[i].proto;
218  r->src_port_or_type_first = ntohs ( rules[i].srcport_or_icmptype_first );
219  r->src_port_or_type_last = ntohs ( rules[i].srcport_or_icmptype_last );
220  r->dst_port_or_code_first = ntohs ( rules[i].dstport_or_icmpcode_first );
221  r->dst_port_or_code_last = ntohs ( rules[i].dstport_or_icmpcode_last );
222  r->tcp_flags_value = rules[i].tcp_flags_value;
223  r->tcp_flags_mask = rules[i].tcp_flags_mask;
224  }
225 
226  if (~0 == *acl_list_index)
227  {
228  /* Get ACL index */
230  memset (a, 0, sizeof (*a));
231  /* Will return the newly allocated ACL index */
232  *acl_list_index = a - am->acls;
233  }
234  else
235  {
236  a = am->acls + *acl_list_index;
237  hash_acl_delete(am, *acl_list_index);
238  /* Get rid of the old rules */
239  if (a->rules)
240  vec_free (a->rules);
241  }
242  a->rules = acl_new_rules;
243  a->count = count;
244  memcpy (a->tag, tag, sizeof (a->tag));
245  hash_acl_add(am, *acl_list_index);
246  clib_mem_set_heap (oldheap);
247  return 0;
248 }
249 
250 static int
251 acl_del_list (u32 acl_list_index)
252 {
253  acl_main_t *am = &acl_main;
254  acl_list_t *a;
255  int i, ii;
256  if (pool_is_free_index (am->acls, acl_list_index))
257  {
258  return -1;
259  }
260 
261  if (acl_list_index < vec_len(am->input_sw_if_index_vec_by_acl)) {
262  if (vec_len(vec_elt(am->input_sw_if_index_vec_by_acl, acl_list_index)) > 0) {
263  /* ACL is applied somewhere inbound. Refuse to delete */
264  return -1;
265  }
266  }
267  if (acl_list_index < vec_len(am->output_sw_if_index_vec_by_acl)) {
268  if (vec_len(vec_elt(am->output_sw_if_index_vec_by_acl, acl_list_index)) > 0) {
269  /* ACL is applied somewhere outbound. Refuse to delete */
270  return -1;
271  }
272  }
273 
274  void *oldheap = acl_set_heap(am);
275  /* delete any references to the ACL */
276  for (i = 0; i < vec_len (am->output_acl_vec_by_sw_if_index); i++)
277  {
278  for (ii = 0; ii < vec_len (am->output_acl_vec_by_sw_if_index[i]);
279  /* see body */ )
280  {
281  if (acl_list_index == am->output_acl_vec_by_sw_if_index[i][ii])
282  {
284  }
285  else
286  {
287  ii++;
288  }
289  }
290  }
291  for (i = 0; i < vec_len (am->input_acl_vec_by_sw_if_index); i++)
292  {
293  for (ii = 0; ii < vec_len (am->input_acl_vec_by_sw_if_index[i]);
294  /* see body */ )
295  {
296  if (acl_list_index == am->input_acl_vec_by_sw_if_index[i][ii])
297  {
299  }
300  else
301  {
302  ii++;
303  }
304  }
305  }
306  /* delete the hash table data */
307 
308  hash_acl_delete(am, acl_list_index);
309  /* now we can delete the ACL itself */
310  a = pool_elt_at_index (am->acls, acl_list_index);
311  if (a->rules)
312  vec_free (a->rules);
313 
314  pool_put (am->acls, a);
315  clib_mem_set_heap (oldheap);
316  return 0;
317 }
318 
319 /* Some aids in ASCII graphing the content */
320 #define XX "\377"
321 #define __ "\000"
322 #define _(x)
323 #define v
324 
326 _(" dmac smac etype ")
327 _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v __ __ v
328  _(" v ihl totlen ")
329  _(0x0000)
330  __ __ __ __
331  _(" ident fl+fo ")
332  _(0x0004)
333  __ __ __ __
334  _(" ttl pr checksum ")
335  _(0x0008)
336  __ XX __ __
337  _(" src address ")
338  _(0x000C)
339  XX XX XX XX
340  _(" dst address ")
341  _(0x0010)
342  XX XX XX XX
343  _("L4 T/U sport dport ")
344  _(tcpudp)
345  XX XX XX XX
346  _(padpad)
347  __ __ __ __
348  _(padpad)
349  __ __ __ __
350  _(padeth)
351  __ __;
352 
354  _(" dmac smac etype ")
355  _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v __ __ v
356  _(" v tc + flow ")
357  _(0x0000) __ __ __ __
358  _(" plen nh hl ")
359  _(0x0004) __ __ XX __
360  _(" src address ")
361  _(0x0008) XX XX XX XX
362  _(0x000C) XX XX XX XX
363  _(0x0010) XX XX XX XX
364  _(0x0014) XX XX XX XX
365  _(" dst address ")
366  _(0x0018) XX XX XX XX
367  _(0x001C) XX XX XX XX
368  _(0x0020) XX XX XX XX
369  _(0x0024) XX XX XX XX
370  _("L4T/U sport dport ")
371  _(tcpudp) XX XX XX XX _(padpad) __ __ __ __ _(padeth) __ __;
372 
373 #undef XX
374 #undef __
375 #undef _
376 #undef v
377 
378  static int count_skip (u8 * p, u32 size)
379 {
380  u64 *p64 = (u64 *) p;
381  /* Be tolerant to null pointer */
382  if (0 == p)
383  return 0;
384 
385  while ((0ULL == *p64) && ((u8 *) p64 - p) < size)
386  {
387  p64++;
388  }
389  return (p64 - (u64 *) p) / 2;
390 }
391 
392 static int
394  u32 mask_len, u32 next_table_index,
395  u32 miss_next_index, u32 * table_index,
396  int is_add)
397 {
398  u32 nbuckets = 1;
399  u32 memory_size = 2 << 13;
400  u32 skip = count_skip (mask, mask_len);
401  u32 match = (mask_len / 16) - skip;
402  u8 *skip_mask_ptr = mask + 16 * skip;
403  u32 current_data_flag = 0;
404  int current_data_offset = 0;
405 
406  if (0 == match)
407  match = 1;
408  void *oldheap = clib_mem_set_heap (cm->vlib_main->heap_base);
409  int ret = vnet_classify_add_del_table (cm, skip_mask_ptr, nbuckets,
410  memory_size, skip, match,
411  next_table_index, miss_next_index,
412  table_index, current_data_flag,
413  current_data_offset, is_add,
414  1 /* delete_chain */);
415  clib_mem_set_heap (oldheap);
416  return ret;
417 }
418 
419 static int
421  u32 mask_len, u32 next_table_index,
422  u32 miss_next_index, u32 * table_index,
423  int is_add)
424 {
425  u32 nbuckets = 32;
426  u32 memory_size = 2 << 20;
427  u32 skip = count_skip (mask, mask_len);
428  u32 match = (mask_len / 16) - skip;
429  u8 *skip_mask_ptr = mask + 16 * skip;
430  u32 current_data_flag = 0;
431  int current_data_offset = 0;
432 
433  if (0 == match)
434  match = 1;
435 
436  void *oldheap = clib_mem_set_heap (cm->vlib_main->heap_base);
437  int ret = vnet_classify_add_del_table (cm, skip_mask_ptr, nbuckets,
438  memory_size, skip, match,
439  next_table_index, miss_next_index,
440  table_index, current_data_flag,
441  current_data_offset, is_add,
442  1 /* delete_chain */);
443  clib_mem_set_heap (oldheap);
444  return ret;
445 }
446 
447 
448 static int
450 {
452  u32 ip4_table_index = ~0;
453  u32 ip6_table_index = ~0;
454  void *oldheap = acl_set_heap(am);
455 
457  sw_if_index, ~0);
459  sw_if_index, ~0);
460 
461  /* switch to global heap while calling vnet_* functions */
462  clib_mem_set_heap (cm->vlib_main->heap_base);
463  vnet_l2_input_classify_enable_disable (sw_if_index, 0);
464 
465  if (am->acl_ip4_input_classify_table_by_sw_if_index[sw_if_index] != ~0)
466  {
467  ip4_table_index =
469  am->acl_ip4_input_classify_table_by_sw_if_index[sw_if_index] = ~0;
470  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
471  sizeof (ip4_5tuple_mask) - 1, ~0,
473  &ip4_table_index, 0);
474  }
475  if (am->acl_ip6_input_classify_table_by_sw_if_index[sw_if_index] != ~0)
476  {
477  ip6_table_index =
479  am->acl_ip6_input_classify_table_by_sw_if_index[sw_if_index] = ~0;
481  sizeof (ip6_5tuple_mask) - 1, ~0,
483  &ip6_table_index, 0);
484  }
485  clib_mem_set_heap (oldheap);
486  return 0;
487 }
488 
489 static int
491 {
493  u32 ip4_table_index = ~0;
494  u32 ip6_table_index = ~0;
495  void *oldheap = acl_set_heap(am);
496 
498  sw_if_index, ~0);
500  sw_if_index, ~0);
501 
502  /* switch to global heap while calling vnet_* functions */
503  clib_mem_set_heap (cm->vlib_main->heap_base);
504 
506 
507  if (am->acl_ip4_output_classify_table_by_sw_if_index[sw_if_index] != ~0)
508  {
509  ip4_table_index =
511  am->acl_ip4_output_classify_table_by_sw_if_index[sw_if_index] = ~0;
512  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
513  sizeof (ip4_5tuple_mask) - 1, ~0,
515  &ip4_table_index, 0);
516  }
517  if (am->acl_ip6_output_classify_table_by_sw_if_index[sw_if_index] != ~0)
518  {
519  ip6_table_index =
521  am->acl_ip6_output_classify_table_by_sw_if_index[sw_if_index] = ~0;
523  sizeof (ip6_5tuple_mask) - 1, ~0,
525  &ip6_table_index, 0);
526  }
527  clib_mem_set_heap (oldheap);
528  return 0;
529 }
530 
531 static int
533 {
535  u32 ip4_table_index = ~0;
536  u32 ip6_table_index = ~0;
537  int rv;
538 
539  void *prevheap = clib_mem_set_heap (cm->vlib_main->heap_base);
540 
541  /* in case there were previous tables attached */
542  acl_unhook_l2_input_classify (am, sw_if_index);
543  rv =
544  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
545  sizeof (ip4_5tuple_mask) - 1, ~0,
547  &ip4_table_index, 1);
548  if (rv)
549  goto done;
550  rv =
552  sizeof (ip6_5tuple_mask) - 1, ~0,
554  &ip6_table_index, 1);
555  if (rv)
556  {
557  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
558  sizeof (ip4_5tuple_mask) - 1, ~0,
560  &ip4_table_index, 0);
561  goto done;
562  }
563  rv =
564  vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index,
565  ip6_table_index, ~0);
566  if (rv)
567  {
569  sizeof (ip6_5tuple_mask) - 1, ~0,
571  &ip6_table_index, 0);
572  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
573  sizeof (ip4_5tuple_mask) - 1, ~0,
575  &ip4_table_index, 0);
576  goto done;
577  }
578 
580  ip4_table_index;
582  ip6_table_index;
583 
584  vnet_l2_input_classify_enable_disable (sw_if_index, 1);
585 done:
586  clib_mem_set_heap (prevheap);
587  return rv;
588 }
589 
590 static int
592 {
594  u32 ip4_table_index = ~0;
595  u32 ip6_table_index = ~0;
596  int rv;
597 
598  void *prevheap = clib_mem_set_heap (cm->vlib_main->heap_base);
599 
600  /* in case there were previous tables attached */
601  acl_unhook_l2_output_classify (am, sw_if_index);
602  rv =
603  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
604  sizeof (ip4_5tuple_mask) - 1, ~0,
606  &ip4_table_index, 1);
607  if (rv)
608  goto done;
609  rv =
611  sizeof (ip6_5tuple_mask) - 1, ~0,
613  &ip6_table_index, 1);
614  if (rv)
615  {
616  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
617  sizeof (ip4_5tuple_mask) - 1, ~0,
619  &ip4_table_index, 0);
620  goto done;
621  }
622  rv =
623  vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index,
624  ip6_table_index, ~0);
626  ("ACL enabling on interface sw_if_index %d, setting tables to the following: ip4: %d ip6: %d\n",
627  sw_if_index, ip4_table_index, ip6_table_index);
628  if (rv)
629  {
631  sizeof (ip6_5tuple_mask) - 1, ~0,
633  &ip6_table_index, 0);
634  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
635  sizeof (ip4_5tuple_mask) - 1, ~0,
637  &ip4_table_index, 0);
638  goto done;
639  }
640 
642  ip4_table_index;
644  ip6_table_index;
645 
647 done:
648  clib_mem_set_heap (prevheap);
649  return rv;
650 }
651 
652 
653 
654 int
656  int enable_disable)
657 {
658  int rv;
659 
660  /* Utterly wrong? */
662  sw_if_index))
663  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
664 
665  acl_fa_enable_disable(sw_if_index, 1, enable_disable);
666 
667  if (enable_disable)
668  {
669  rv = acl_hook_l2_input_classify (am, sw_if_index);
670  }
671  else
672  {
673  rv = acl_unhook_l2_input_classify (am, sw_if_index);
674  }
675 
676  return rv;
677 }
678 
679 int
681  int enable_disable)
682 {
683  int rv;
684 
685  /* Utterly wrong? */
687  sw_if_index))
688  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
689 
690  acl_fa_enable_disable(sw_if_index, 0, enable_disable);
691 
692  if (enable_disable)
693  {
694  rv = acl_hook_l2_output_classify (am, sw_if_index);
695  }
696  else
697  {
698  rv = acl_unhook_l2_output_classify (am, sw_if_index);
699  }
700 
701  return rv;
702 }
703 
704 static int
705 acl_is_not_defined(acl_main_t *am, u32 acl_list_index)
706 {
707  return (pool_is_free_index (am->acls, acl_list_index));
708 }
709 
710 
711 static int
712 acl_interface_add_inout_acl (u32 sw_if_index, u8 is_input, u32 acl_list_index)
713 {
714  acl_main_t *am = &acl_main;
715  if (acl_is_not_defined(am, acl_list_index)) {
716  /* ACL is not defined. Can not apply */
717  return -1;
718  }
719  void *oldheap = acl_set_heap(am);
720 
721  if (is_input)
722  {
723  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
724 
725  u32 index = vec_search(am->input_acl_vec_by_sw_if_index[sw_if_index], acl_list_index);
726  if (index < vec_len(am->input_acl_vec_by_sw_if_index[sw_if_index])) {
727  clib_warning("ACL %d is already applied inbound on sw_if_index %d (index %d)",
728  acl_list_index, sw_if_index, index);
729  /* the entry is already there */
730  clib_mem_set_heap (oldheap);
731  return -1;
732  }
733  /* if there was no ACL applied before, enable the ACL processing */
734  if (vec_len(am->input_acl_vec_by_sw_if_index[sw_if_index]) == 0) {
735  acl_interface_in_enable_disable (am, sw_if_index, 1);
736  }
737  vec_add (am->input_acl_vec_by_sw_if_index[sw_if_index], &acl_list_index,
738  1);
739  vec_validate (am->input_sw_if_index_vec_by_acl, acl_list_index);
740  vec_add (am->input_sw_if_index_vec_by_acl[acl_list_index], &sw_if_index,
741  1);
742  }
743  else
744  {
745  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
746 
747  u32 index = vec_search(am->output_acl_vec_by_sw_if_index[sw_if_index], acl_list_index);
748  if (index < vec_len(am->output_acl_vec_by_sw_if_index[sw_if_index])) {
749  clib_warning("ACL %d is already applied outbound on sw_if_index %d (index %d)",
750  acl_list_index, sw_if_index, index);
751  /* the entry is already there */
752  clib_mem_set_heap (oldheap);
753  return -1;
754  }
755  /* if there was no ACL applied before, enable the ACL processing */
756  if (vec_len(am->output_acl_vec_by_sw_if_index[sw_if_index]) == 0) {
757  acl_interface_out_enable_disable (am, sw_if_index, 1);
758  }
759  vec_add (am->output_acl_vec_by_sw_if_index[sw_if_index],
760  &acl_list_index, 1);
761  vec_validate (am->output_sw_if_index_vec_by_acl, acl_list_index);
762  vec_add (am->output_sw_if_index_vec_by_acl[acl_list_index], &sw_if_index,
763  1);
764  }
765  clib_mem_set_heap (oldheap);
766  return 0;
767 }
768 
769 
770 static int
771 acl_interface_del_inout_acl (u32 sw_if_index, u8 is_input, u32 acl_list_index)
772 {
773  acl_main_t *am = &acl_main;
774  int i;
775  int rv = -1;
776  void *oldheap = acl_set_heap(am);
777  if (is_input)
778  {
779  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
780  for (i = 0; i < vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]);
781  i++)
782  {
783  if (acl_list_index ==
784  am->input_acl_vec_by_sw_if_index[sw_if_index][i])
785  {
786  vec_del1 (am->input_acl_vec_by_sw_if_index[sw_if_index], i);
787  rv = 0;
788  break;
789  }
790  }
791 
792  if (acl_list_index < vec_len(am->input_sw_if_index_vec_by_acl)) {
793  u32 index = vec_search(am->input_sw_if_index_vec_by_acl[acl_list_index], sw_if_index);
794  if (index < vec_len(am->input_sw_if_index_vec_by_acl[acl_list_index])) {
795  hash_acl_unapply(am, sw_if_index, is_input, acl_list_index);
796  vec_del1 (am->input_sw_if_index_vec_by_acl[acl_list_index], index);
797  }
798  }
799 
800  /* If there is no more ACLs applied on an interface, disable ACL processing */
801  if (0 == vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]))
802  {
803  acl_interface_in_enable_disable (am, sw_if_index, 0);
804  }
805  }
806  else
807  {
808  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
809  for (i = 0;
810  i < vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]); i++)
811  {
812  if (acl_list_index ==
813  am->output_acl_vec_by_sw_if_index[sw_if_index][i])
814  {
815  vec_del1 (am->output_acl_vec_by_sw_if_index[sw_if_index], i);
816  rv = 0;
817  break;
818  }
819  }
820 
821  if (acl_list_index < vec_len(am->output_sw_if_index_vec_by_acl)) {
822  u32 index = vec_search(am->output_sw_if_index_vec_by_acl[acl_list_index], sw_if_index);
823  if (index < vec_len(am->output_sw_if_index_vec_by_acl[acl_list_index])) {
824  hash_acl_unapply(am, sw_if_index, is_input, acl_list_index);
825  vec_del1 (am->output_sw_if_index_vec_by_acl[acl_list_index], index);
826  }
827  }
828 
829  /* If there is no more ACLs applied on an interface, disable ACL processing */
830  if (0 == vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]))
831  {
832  acl_interface_out_enable_disable (am, sw_if_index, 0);
833  }
834  }
835  clib_mem_set_heap (oldheap);
836  return rv;
837 }
838 
839 static void
840 acl_interface_reset_inout_acls (u32 sw_if_index, u8 is_input)
841 {
842  acl_main_t *am = &acl_main;
843  int i;
844  void *oldheap = acl_set_heap(am);
845  if (is_input)
846  {
847  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
848  if (vec_len(am->input_acl_vec_by_sw_if_index[sw_if_index]) > 0) {
849  acl_interface_in_enable_disable (am, sw_if_index, 0);
850  }
851 
852  for(i = vec_len(am->input_acl_vec_by_sw_if_index[sw_if_index])-1; i>=0; i--) {
853  u32 acl_list_index = am->input_acl_vec_by_sw_if_index[sw_if_index][i];
854  hash_acl_unapply(am, sw_if_index, is_input, acl_list_index);
855  if (acl_list_index < vec_len(am->input_sw_if_index_vec_by_acl)) {
856  u32 index = vec_search(am->input_sw_if_index_vec_by_acl[acl_list_index], sw_if_index);
857  if (index < vec_len(am->input_sw_if_index_vec_by_acl[acl_list_index])) {
858  vec_del1 (am->input_sw_if_index_vec_by_acl[acl_list_index], index);
859  }
860  }
861  }
862 
864  }
865  else
866  {
867  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
868  if (vec_len(am->output_acl_vec_by_sw_if_index[sw_if_index]) > 0) {
869  acl_interface_out_enable_disable (am, sw_if_index, 0);
870  }
871 
872  for(i = vec_len(am->output_acl_vec_by_sw_if_index[sw_if_index])-1; i>=0; i--) {
873  u32 acl_list_index = am->output_acl_vec_by_sw_if_index[sw_if_index][i];
874  hash_acl_unapply(am, sw_if_index, is_input, acl_list_index);
875  if (acl_list_index < vec_len(am->output_sw_if_index_vec_by_acl)) {
876  u32 index = vec_search(am->output_sw_if_index_vec_by_acl[acl_list_index], sw_if_index);
877  if (index < vec_len(am->output_sw_if_index_vec_by_acl[acl_list_index])) {
878  vec_del1 (am->output_sw_if_index_vec_by_acl[acl_list_index], index);
879  }
880  }
881  }
882 
884  }
885  clib_mem_set_heap (oldheap);
886 }
887 
888 static int
889 acl_interface_add_del_inout_acl (u32 sw_if_index, u8 is_add, u8 is_input,
890  u32 acl_list_index)
891 {
892  int rv = -1;
893  acl_main_t *am = &acl_main;
894  if (is_add)
895  {
896  rv =
897  acl_interface_add_inout_acl (sw_if_index, is_input, acl_list_index);
898  if (rv == 0)
899  {
900  hash_acl_apply(am, sw_if_index, is_input, acl_list_index);
901  }
902  }
903  else
904  {
905  hash_acl_unapply(am, sw_if_index, is_input, acl_list_index);
906  rv =
907  acl_interface_del_inout_acl (sw_if_index, is_input, acl_list_index);
908  }
909  return rv;
910 }
911 
912 
913 typedef struct
914 {
916  u8 mac_mask[6];
922 
923 static u32
924 macip_find_match_type (macip_match_type_t * mv, u8 * mac_mask, u8 prefix_len,
925  u8 is_ipv6)
926 {
927  u32 i;
928  if (mv)
929  {
930  for (i = 0; i < vec_len (mv); i++)
931  {
932  if ((mv[i].prefix_len == prefix_len) && (mv[i].is_ipv6 == is_ipv6)
933  && (0 == memcmp (mv[i].mac_mask, mac_mask, 6)))
934  {
935  return i;
936  }
937  }
938  }
939  return ~0;
940 }
941 
942 
943 /* Get metric used to sort match types.
944  The more specific and the more often seen - the bigger the metric */
945 static int
947 {
948  unsigned int mac_bits_set = 0;
949  unsigned int mac_byte;
950  int i;
951  for (i=0; i<6; i++)
952  {
953  mac_byte = m->mac_mask[i];
954  for (; mac_byte; mac_byte >>= 1)
955  mac_bits_set += mac_byte & 1;
956  }
957  /*
958  * Attempt to place the more specific and the more used rules on top.
959  * There are obvious caveat corner cases to this, but they do not
960  * seem to be sensible in real world (e.g. specific IPv4 with wildcard MAC
961  * going with a wildcard IPv4 with a specific MAC).
962  */
963  return m->prefix_len + mac_bits_set + m->is_ipv6 + 10 * m->count;
964 }
965 
966 static int
968 {
969  /* Ascending sort based on the metric values */
970  return match_type_metric (m1) - match_type_metric (m2);
971 }
972 
973 /* Get the offset of L3 source within ethernet packet */
974 static int
976 {
977  if(is6)
978  return (sizeof(ethernet_header_t) + offsetof(ip6_header_t, src_address));
979  else
980  return (sizeof(ethernet_header_t) + offsetof(ip4_header_t, src_address));
981 }
982 
983 static int
985 {
986  macip_match_type_t *mvec = NULL;
987  macip_match_type_t *mt;
988  macip_acl_list_t *a = pool_elt_at_index (am->macip_acls, macip_acl_index);
989  int i;
990  u32 match_type_index;
991  u32 last_table;
992  u8 mask[5 * 16];
994 
995  /* Count the number of different types of rules */
996  for (i = 0; i < a->count; i++)
997  {
998  if (~0 ==
999  (match_type_index =
1001  a->rules[i].src_prefixlen,
1002  a->rules[i].is_ipv6)))
1003  {
1004  match_type_index = vec_len (mvec);
1005  vec_validate (mvec, match_type_index);
1006  memcpy (mvec[match_type_index].mac_mask,
1007  a->rules[i].src_mac_mask, 6);
1008  mvec[match_type_index].prefix_len = a->rules[i].src_prefixlen;
1009  mvec[match_type_index].is_ipv6 = a->rules[i].is_ipv6;
1010  mvec[match_type_index].table_index = ~0;
1011  }
1012  mvec[match_type_index].count++;
1013  }
1014  /* Put the most frequently used tables last in the list so we can create classifier tables in reverse order */
1016  /* Create the classifier tables */
1017  last_table = ~0;
1018  /* First add ARP tables */
1019  vec_foreach (mt, mvec)
1020  {
1021  int mask_len;
1022  int is6 = mt->is_ipv6;
1023 
1024  mt->arp_table_index = ~0;
1025  if (!is6)
1026  {
1027  memset (mask, 0, sizeof (mask));
1028  memcpy (&mask[6], mt->mac_mask, 6);
1029  memset (&mask[12], 0xff, 2); /* ethernet protocol */
1030  memcpy (&mask[14 + 8], mt->mac_mask, 6);
1031 
1032  for (i = 0; i < (mt->prefix_len / 8); i++)
1033  mask[14 + 14 + i] = 0xff;
1034  if (mt->prefix_len % 8)
1035  mask[14 + 14 + (mt->prefix_len / 8)] = 0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
1036 
1037  mask_len = ((14 + 14 + ((mt->prefix_len+7) / 8) +
1038  (sizeof (u32x4)-1))/sizeof(u32x4)) * sizeof (u32x4);
1039  acl_classify_add_del_table_small (cm, mask, mask_len, last_table,
1040  (~0 == last_table) ? 0 : ~0, &mt->arp_table_index,
1041  1);
1042  last_table = mt->arp_table_index;
1043  }
1044  }
1045  /* Now add IP[46] tables */
1046  vec_foreach (mt, mvec)
1047  {
1048  int mask_len;
1049  int is6 = mt->is_ipv6;
1050  int l3_src_offs = get_l3_src_offset(is6);
1051  memset (mask, 0, sizeof (mask));
1052  memcpy (&mask[6], mt->mac_mask, 6);
1053  for (i = 0; i < (mt->prefix_len / 8); i++)
1054  {
1055  mask[l3_src_offs + i] = 0xff;
1056  }
1057  if (mt->prefix_len % 8)
1058  {
1059  mask[l3_src_offs + (mt->prefix_len / 8)] =
1060  0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
1061  }
1062  /*
1063  * Round-up the number of bytes needed to store the prefix,
1064  * and round up the number of vectors too
1065  */
1066  mask_len = ((l3_src_offs + ((mt->prefix_len+7) / 8) +
1067  (sizeof (u32x4)-1))/sizeof(u32x4)) * sizeof (u32x4);
1068  acl_classify_add_del_table_small (cm, mask, mask_len, last_table,
1069  (~0 == last_table) ? 0 : ~0, &mt->table_index,
1070  1);
1071  last_table = mt->table_index;
1072  }
1073  a->ip4_table_index = last_table;
1074  a->ip6_table_index = last_table;
1075  a->l2_table_index = last_table;
1076 
1077  /* Populate the classifier tables with rules from the MACIP ACL */
1078  for (i = 0; i < a->count; i++)
1079  {
1080  u32 action = 0;
1081  u32 metadata = 0;
1082  int is6 = a->rules[i].is_ipv6;
1083  int l3_src_offs = get_l3_src_offset(is6);
1084  memset (mask, 0, sizeof (mask));
1085  memcpy (&mask[6], a->rules[i].src_mac, 6);
1086  memset (&mask[12], 0xff, 2); /* ethernet protocol */
1087  if (is6)
1088  {
1089  memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip6, 16);
1090  mask[12] = 0x86;
1091  mask[13] = 0xdd;
1092  }
1093  else
1094  {
1095  memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip4, 4);
1096  mask[12] = 0x08;
1097  mask[13] = 0x00;
1098  }
1099  match_type_index =
1101  a->rules[i].src_prefixlen,
1102  a->rules[i].is_ipv6);
1103  ASSERT(match_type_index != ~0);
1104  /* add session to table mvec[match_type_index].table_index; */
1105  vnet_classify_add_del_session (cm, mvec[match_type_index].table_index,
1106  mask, a->rules[i].is_permit ? ~0 : 0, i,
1107  0, action, metadata, 1);
1108  /* add ARP table entry too */
1109  if (!is6 && (mvec[match_type_index].arp_table_index != ~0))
1110  {
1111  memset (mask, 0, sizeof (mask));
1112  memcpy (&mask[6], a->rules[i].src_mac, 6);
1113  mask[12] = 0x08;
1114  mask[13] = 0x06;
1115  memcpy (&mask[14 + 8], a->rules[i].src_mac, 6);
1116  memcpy (&mask[14 + 14], &a->rules[i].src_ip_addr.ip4, 4);
1117  vnet_classify_add_del_session (cm, mvec[match_type_index].arp_table_index,
1118  mask, a->rules[i].is_permit ? ~0 : 0, i,
1119  0, action, metadata, 1);
1120  }
1121  }
1122  return 0;
1123 }
1124 
1125 static void
1127 {
1129  macip_acl_list_t *a = pool_elt_at_index (am->macip_acls, macip_acl_index);
1130 
1131  if (a->ip4_table_index != ~0)
1132  {
1133  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0, &a->ip4_table_index, 0);
1134  a->ip4_table_index = ~0;
1135  }
1136  if (a->ip6_table_index != ~0)
1137  {
1138  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0, &a->ip6_table_index, 0);
1139  a->ip6_table_index = ~0;
1140  }
1141  if (a->l2_table_index != ~0)
1142  {
1143  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0, &a->l2_table_index, 0);
1144  a->l2_table_index = ~0;
1145  }
1146 }
1147 
1148 static int
1150  u32 * acl_list_index, u8 * tag)
1151 {
1152  acl_main_t *am = &acl_main;
1154  macip_acl_rule_t *r;
1155  macip_acl_rule_t *acl_new_rules = 0;
1156  int i;
1157 
1158  if (*acl_list_index != ~0)
1159  {
1160  /* They supplied some number, let's see if this MACIP ACL exists */
1161  if (pool_is_free_index (am->macip_acls, *acl_list_index))
1162  {
1163  /* tried to replace a non-existent ACL, no point doing anything */
1164  clib_warning("acl-plugin-error: Trying to replace nonexistent MACIP ACL %d (tag %s)", *acl_list_index, tag);
1165  return -1;
1166  }
1167  }
1168 
1169  if (0 == count) {
1170  clib_warning("acl-plugin-warning: Trying to create empty MACIP ACL (tag %s)", tag);
1171  }
1172  void *oldheap = acl_set_heap(am);
1173  /* Create and populate the rules */
1174  if (count > 0)
1175  vec_validate(acl_new_rules, count-1);
1176 
1177  for (i = 0; i < count; i++)
1178  {
1179  r = &acl_new_rules[i];
1180  r->is_permit = rules[i].is_permit;
1181  r->is_ipv6 = rules[i].is_ipv6;
1182  memcpy (&r->src_mac, rules[i].src_mac, 6);
1183  memcpy (&r->src_mac_mask, rules[i].src_mac_mask, 6);
1184  if(rules[i].is_ipv6)
1185  memcpy (&r->src_ip_addr.ip6, rules[i].src_ip_addr, 16);
1186  else
1187  memcpy (&r->src_ip_addr.ip4, rules[i].src_ip_addr, 4);
1188  r->src_prefixlen = rules[i].src_ip_prefix_len;
1189  }
1190 
1191  if (~0 == *acl_list_index)
1192  {
1193  /* Get ACL index */
1195  memset (a, 0, sizeof (*a));
1196  /* Will return the newly allocated ACL index */
1197  *acl_list_index = a - am->macip_acls;
1198  }
1199  else
1200  {
1201  a = pool_elt_at_index (am->macip_acls, *acl_list_index);
1202  if (a->rules)
1203  {
1204  vec_free (a->rules);
1205  }
1206  macip_destroy_classify_tables (am, *acl_list_index);
1207  }
1208 
1209  a->rules = acl_new_rules;
1210  a->count = count;
1211  memcpy (a->tag, tag, sizeof (a->tag));
1212 
1213  /* Create and populate the classifer tables */
1214  macip_create_classify_tables (am, *acl_list_index);
1215  clib_mem_set_heap (oldheap);
1216  return 0;
1217 }
1218 
1219 
1220 /* No check for validity of sw_if_index - the callers were supposed to validate */
1221 
1222 static int
1224 {
1225  int rv;
1226  u32 macip_acl_index;
1228  void *oldheap = acl_set_heap(am);
1229  vec_validate_init_empty (am->macip_acl_by_sw_if_index, sw_if_index, ~0);
1230  clib_mem_set_heap (oldheap);
1231  macip_acl_index = am->macip_acl_by_sw_if_index[sw_if_index];
1232  /* No point in deleting MACIP ACL which is not applied */
1233  if (~0 == macip_acl_index)
1234  return -1;
1235  a = pool_elt_at_index (am->macip_acls, macip_acl_index);
1236  /* remove the classifier tables off the interface L2 ACL */
1237  rv =
1238  vnet_set_input_acl_intfc (am->vlib_main, sw_if_index, a->ip4_table_index,
1239  a->ip6_table_index, a->l2_table_index, 0);
1240  /* Unset the MACIP ACL index */
1241  am->macip_acl_by_sw_if_index[sw_if_index] = ~0;
1242  return rv;
1243 }
1244 
1245 /* No check for validity of sw_if_index - the callers were supposed to validate */
1246 
1247 static int
1249  u32 macip_acl_index)
1250 {
1252  int rv;
1253  if (pool_is_free_index (am->macip_acls, macip_acl_index))
1254  {
1255  return -1;
1256  }
1257  void *oldheap = acl_set_heap(am);
1258  a = pool_elt_at_index (am->macip_acls, macip_acl_index);
1259  vec_validate_init_empty (am->macip_acl_by_sw_if_index, sw_if_index, ~0);
1260  clib_mem_set_heap (oldheap);
1261  /* If there already a MACIP ACL applied, unapply it */
1262  if (~0 != am->macip_acl_by_sw_if_index[sw_if_index])
1263  macip_acl_interface_del_acl(am, sw_if_index);
1264  am->macip_acl_by_sw_if_index[sw_if_index] = macip_acl_index;
1265 
1266  /* Apply the classifier tables for L2 ACLs */
1267  rv =
1268  vnet_set_input_acl_intfc (am->vlib_main, sw_if_index, a->ip4_table_index,
1269  a->ip6_table_index, a->l2_table_index, 1);
1270  return rv;
1271 }
1272 
1273 static int
1274 macip_acl_del_list (u32 acl_list_index)
1275 {
1276  acl_main_t *am = &acl_main;
1278  int i;
1279  if (pool_is_free_index (am->macip_acls, acl_list_index))
1280  {
1281  return -1;
1282  }
1283 
1284  /* delete any references to the ACL */
1285  for (i = 0; i < vec_len (am->macip_acl_by_sw_if_index); i++)
1286  {
1287  if (am->macip_acl_by_sw_if_index[i] == acl_list_index)
1288  {
1290  }
1291  }
1292 
1293  void *oldheap = acl_set_heap(am);
1294  /* Now that classifier tables are detached, clean them up */
1295  macip_destroy_classify_tables (am, acl_list_index);
1296 
1297  /* now we can delete the ACL itself */
1298  a = pool_elt_at_index (am->macip_acls, acl_list_index);
1299  if (a->rules)
1300  {
1301  vec_free (a->rules);
1302  }
1303  pool_put (am->macip_acls, a);
1304  clib_mem_set_heap (oldheap);
1305  return 0;
1306 }
1307 
1308 
1309 static int
1311  u32 acl_list_index)
1312 {
1313  acl_main_t *am = &acl_main;
1314  int rv = -1;
1315  if (is_add)
1316  {
1317  rv = macip_acl_interface_add_acl (am, sw_if_index, acl_list_index);
1318  }
1319  else
1320  {
1321  rv = macip_acl_interface_del_acl (am, sw_if_index);
1322  }
1323  return rv;
1324 }
1325 
1326 /*
1327  * If the client does not allocate enough memory for a variable-length
1328  * message, and then proceed to use it as if the full memory allocated,
1329  * absent the check we happily consume that on the VPP side, and go
1330  * along as if nothing happened. However, the resulting
1331  * effects range from just garbage in the API decode
1332  * (because the decoder snoops too far), to potential memory
1333  * corruptions.
1334  *
1335  * This verifies that the actual length of the message is
1336  * at least expected_len, and complains loudly if it is not.
1337  *
1338  * A failing check here is 100% a software bug on the API user side,
1339  * so we might as well yell.
1340  *
1341  */
1342 static int verify_message_len(void *mp, u32 expected_len, char *where)
1343 {
1344  u32 supplied_len = vl_msg_api_get_msg_length (mp);
1345  if (supplied_len < expected_len) {
1346  clib_warning("%s: Supplied message length %d is less than expected %d",
1347  where, supplied_len, expected_len);
1348  return 0;
1349  } else {
1350  return 1;
1351  }
1352 }
1353 
1354 /* API message handler */
1355 static void
1357 {
1359  acl_main_t *am = &acl_main;
1360  int rv;
1361  u32 acl_list_index = ntohl (mp->acl_index);
1362  u32 acl_count = ntohl (mp->count);
1363  u32 expected_len = sizeof(*mp) + acl_count*sizeof(mp->r[0]);
1364 
1365  if (verify_message_len(mp, expected_len, "acl_add_replace")) {
1366  rv = acl_add_list (acl_count, mp->r, &acl_list_index, mp->tag);
1367  } else {
1368  rv = VNET_API_ERROR_INVALID_VALUE;
1369  }
1370 
1371  /* *INDENT-OFF* */
1372  REPLY_MACRO2(VL_API_ACL_ADD_REPLACE_REPLY,
1373  ({
1374  rmp->acl_index = htonl(acl_list_index);
1375  }));
1376  /* *INDENT-ON* */
1377 }
1378 
1379 static void
1381 {
1382  acl_main_t *am = &acl_main;
1383  vl_api_acl_del_reply_t *rmp;
1384  int rv;
1385 
1386  rv = acl_del_list (ntohl (mp->acl_index));
1387 
1388  REPLY_MACRO (VL_API_ACL_DEL_REPLY);
1389 }
1390 
1391 static void
1393 {
1394  acl_main_t *am = &acl_main;
1396  u32 sw_if_index = ntohl (mp->sw_if_index);
1397  vl_api_acl_interface_add_del_reply_t *rmp;
1398  int rv = -1;
1399 
1400  if (pool_is_free_index(im->sw_interfaces, sw_if_index))
1401  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1402  else
1403  rv =
1404  acl_interface_add_del_inout_acl (sw_if_index, mp->is_add,
1405  mp->is_input, ntohl (mp->acl_index));
1406 
1407  REPLY_MACRO (VL_API_ACL_INTERFACE_ADD_DEL_REPLY);
1408 }
1409 
1410 static void
1413 {
1414  acl_main_t *am = &acl_main;
1415  vl_api_acl_interface_set_acl_list_reply_t *rmp;
1416  int rv = 0;
1417  int i;
1419  u32 sw_if_index = ntohl (mp->sw_if_index);
1420 
1421  if (pool_is_free_index(im->sw_interfaces, sw_if_index))
1422  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1423  else
1424  {
1425  acl_interface_reset_inout_acls (sw_if_index, 0);
1426  acl_interface_reset_inout_acls (sw_if_index, 1);
1427 
1428  for (i = 0; i < mp->count; i++)
1429  {
1430  if(acl_is_not_defined(am, ntohl (mp->acls[i]))) {
1431  /* ACL does not exist, so we can not apply it */
1432  rv = -1;
1433  }
1434  }
1435  if (0 == rv) {
1436  for (i = 0; i < mp->count; i++)
1437  {
1438  acl_interface_add_del_inout_acl (sw_if_index, 1, (i < mp->n_input),
1439  ntohl (mp->acls[i]));
1440  }
1441  }
1442  }
1443 
1444  REPLY_MACRO (VL_API_ACL_INTERFACE_SET_ACL_LIST_REPLY);
1445 }
1446 
1447 static void
1449 {
1450  api_rule->is_permit = r->is_permit;
1451  api_rule->is_ipv6 = r->is_ipv6;
1452  if(r->is_ipv6)
1453  {
1454  memcpy (api_rule->src_ip_addr, &r->src, sizeof (r->src));
1455  memcpy (api_rule->dst_ip_addr, &r->dst, sizeof (r->dst));
1456  }
1457  else
1458  {
1459  memcpy (api_rule->src_ip_addr, &r->src.ip4, sizeof (r->src.ip4));
1460  memcpy (api_rule->dst_ip_addr, &r->dst.ip4, sizeof (r->dst.ip4));
1461  }
1462  api_rule->src_ip_prefix_len = r->src_prefixlen;
1463  api_rule->dst_ip_prefix_len = r->dst_prefixlen;
1464  api_rule->proto = r->proto;
1465  api_rule->srcport_or_icmptype_first = htons (r->src_port_or_type_first);
1466  api_rule->srcport_or_icmptype_last = htons (r->src_port_or_type_last);
1467  api_rule->dstport_or_icmpcode_first = htons (r->dst_port_or_code_first);
1468  api_rule->dstport_or_icmpcode_last = htons (r->dst_port_or_code_last);
1469  api_rule->tcp_flags_mask = r->tcp_flags_mask;
1470  api_rule->tcp_flags_value = r->tcp_flags_value;
1471 }
1472 
1473 static void
1475  acl_list_t * acl, u32 context)
1476 {
1478  vl_api_acl_rule_t *rules;
1479  int i;
1480  int msg_size = sizeof (*mp) + sizeof (mp->r[0]) * acl->count;
1481  void *oldheap = acl_set_heap(am);
1482 
1483  mp = vl_msg_api_alloc (msg_size);
1484  memset (mp, 0, msg_size);
1485  mp->_vl_msg_id = ntohs (VL_API_ACL_DETAILS + am->msg_id_base);
1486 
1487  /* fill in the message */
1488  mp->context = context;
1489  mp->count = htonl (acl->count);
1490  mp->acl_index = htonl (acl - am->acls);
1491  memcpy (mp->tag, acl->tag, sizeof (mp->tag));
1492  // clib_memcpy (mp->r, acl->rules, acl->count * sizeof(acl->rules[0]));
1493  rules = mp->r;
1494  for (i = 0; i < acl->count; i++)
1495  {
1496  copy_acl_rule_to_api_rule (&rules[i], &acl->rules[i]);
1497  }
1498 
1499  clib_mem_set_heap (oldheap);
1500  vl_msg_api_send_shmem (q, (u8 *) & mp);
1501 }
1502 
1503 
1504 static void
1506 {
1507  acl_main_t *am = &acl_main;
1508  u32 acl_index;
1509  acl_list_t *acl;
1510 
1511  int rv = -1;
1513 
1515  if (q == 0)
1516  {
1517  return;
1518  }
1519 
1520  if (mp->acl_index == ~0)
1521  {
1522  /* *INDENT-OFF* */
1523  /* Just dump all ACLs */
1524  pool_foreach (acl, am->acls,
1525  ({
1526  send_acl_details(am, q, acl, mp->context);
1527  }));
1528  /* *INDENT-ON* */
1529  }
1530  else
1531  {
1532  acl_index = ntohl (mp->acl_index);
1533  if (!pool_is_free_index (am->acls, acl_index))
1534  {
1535  acl = pool_elt_at_index (am->acls, acl_index);
1536  send_acl_details (am, q, acl, mp->context);
1537  }
1538  }
1539 
1540  if (rv == -1)
1541  {
1542  /* FIXME API: should we signal an error here at all ? */
1543  return;
1544  }
1545 }
1546 
1547 static void
1550  u32 sw_if_index, u32 context)
1551 {
1553  int msg_size;
1554  int n_input;
1555  int n_output;
1556  int count;
1557  int i = 0;
1558  void *oldheap = acl_set_heap(am);
1559 
1560  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
1561  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
1562 
1563  n_input = vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]);
1564  n_output = vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]);
1565  count = n_input + n_output;
1566 
1567  msg_size = sizeof (*mp);
1568  msg_size += sizeof (mp->acls[0]) * count;
1569 
1570  mp = vl_msg_api_alloc (msg_size);
1571  memset (mp, 0, msg_size);
1572  mp->_vl_msg_id =
1573  ntohs (VL_API_ACL_INTERFACE_LIST_DETAILS + am->msg_id_base);
1574 
1575  /* fill in the message */
1576  mp->context = context;
1577  mp->sw_if_index = htonl (sw_if_index);
1578  mp->count = count;
1579  mp->n_input = n_input;
1580  for (i = 0; i < n_input; i++)
1581  {
1582  mp->acls[i] = htonl (am->input_acl_vec_by_sw_if_index[sw_if_index][i]);
1583  }
1584  for (i = 0; i < n_output; i++)
1585  {
1586  mp->acls[n_input + i] =
1587  htonl (am->output_acl_vec_by_sw_if_index[sw_if_index][i]);
1588  }
1589  clib_mem_set_heap (oldheap);
1590  vl_msg_api_send_shmem (q, (u8 *) & mp);
1591 }
1592 
1593 static void
1595  mp)
1596 {
1597  acl_main_t *am = &acl_main;
1598  vnet_sw_interface_t *swif;
1600 
1601  u32 sw_if_index;
1603 
1605  if (q == 0)
1606  {
1607  return;
1608  }
1609 
1610  if (mp->sw_if_index == ~0)
1611  {
1612  /* *INDENT-OFF* */
1613  pool_foreach (swif, im->sw_interfaces,
1614  ({
1615  send_acl_interface_list_details(am, q, swif->sw_if_index, mp->context);
1616  }));
1617  /* *INDENT-ON* */
1618  }
1619  else
1620  {
1621  sw_if_index = ntohl (mp->sw_if_index);
1622  if (!pool_is_free_index(im->sw_interfaces, sw_if_index))
1623  send_acl_interface_list_details (am, q, sw_if_index, mp->context);
1624  }
1625 }
1626 
1627 /* MACIP ACL API handlers */
1628 
1629 static void
1631 {
1633  acl_main_t *am = &acl_main;
1634  int rv;
1635  u32 acl_list_index = ~0;
1636  u32 acl_count = ntohl (mp->count);
1637  u32 expected_len = sizeof(*mp) + acl_count*sizeof(mp->r[0]);
1638 
1639  if (verify_message_len(mp, expected_len, "macip_acl_add")) {
1640  rv = macip_acl_add_list (acl_count, mp->r, &acl_list_index, mp->tag);
1641  } else {
1642  rv = VNET_API_ERROR_INVALID_VALUE;
1643  }
1644 
1645  /* *INDENT-OFF* */
1646  REPLY_MACRO2(VL_API_MACIP_ACL_ADD_REPLY,
1647  ({
1648  rmp->acl_index = htonl(acl_list_index);
1649  }));
1650  /* *INDENT-ON* */
1651 }
1652 
1653 static void
1655 {
1657  acl_main_t *am = &acl_main;
1658  int rv;
1659  u32 acl_list_index = ntohl (mp->acl_index);
1660  u32 acl_count = ntohl (mp->count);
1661  u32 expected_len = sizeof(*mp) + acl_count*sizeof(mp->r[0]);
1662 
1663  if (verify_message_len(mp, expected_len, "macip_acl_add_replace")) {
1664  rv = macip_acl_add_list (acl_count, mp->r, &acl_list_index, mp->tag);
1665  } else {
1666  rv = VNET_API_ERROR_INVALID_VALUE;
1667  }
1668 
1669  /* *INDENT-OFF* */
1670  REPLY_MACRO2(VL_API_MACIP_ACL_ADD_REPLACE_REPLY,
1671  ({
1672  rmp->acl_index = htonl(acl_list_index);
1673  }));
1674  /* *INDENT-ON* */
1675 }
1676 
1677 static void
1679 {
1680  acl_main_t *am = &acl_main;
1681  vl_api_macip_acl_del_reply_t *rmp;
1682  int rv;
1683 
1684  rv = macip_acl_del_list (ntohl (mp->acl_index));
1685 
1686  REPLY_MACRO (VL_API_MACIP_ACL_DEL_REPLY);
1687 }
1688 
1689 static void
1692 {
1693  acl_main_t *am = &acl_main;
1694  vl_api_macip_acl_interface_add_del_reply_t *rmp;
1695  int rv = -1;
1697  u32 sw_if_index = ntohl (mp->sw_if_index);
1698 
1699  if (pool_is_free_index(im->sw_interfaces, sw_if_index))
1700  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1701  else
1702  rv =
1704  ntohl (mp->acl_index));
1705 
1706  REPLY_MACRO (VL_API_MACIP_ACL_INTERFACE_ADD_DEL_REPLY);
1707 }
1708 
1709 static void
1711  macip_acl_list_t * acl, u32 context)
1712 {
1714  vl_api_macip_acl_rule_t *rules;
1715  macip_acl_rule_t *r;
1716  int i;
1717  int msg_size = sizeof (*mp) + (acl ? sizeof (mp->r[0]) * acl->count : 0);
1718 
1719  mp = vl_msg_api_alloc (msg_size);
1720  memset (mp, 0, msg_size);
1721  mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_DETAILS + am->msg_id_base);
1722 
1723  /* fill in the message */
1724  mp->context = context;
1725  if (acl)
1726  {
1727  memcpy (mp->tag, acl->tag, sizeof (mp->tag));
1728  mp->count = htonl (acl->count);
1729  mp->acl_index = htonl (acl - am->macip_acls);
1730  rules = mp->r;
1731  for (i = 0; i < acl->count; i++)
1732  {
1733  r = &acl->rules[i];
1734  rules[i].is_permit = r->is_permit;
1735  rules[i].is_ipv6 = r->is_ipv6;
1736  memcpy (rules[i].src_mac, &r->src_mac, sizeof (r->src_mac));
1737  memcpy (rules[i].src_mac_mask, &r->src_mac_mask,
1738  sizeof (r->src_mac_mask));
1739  if (r->is_ipv6)
1740  memcpy (rules[i].src_ip_addr, &r->src_ip_addr.ip6,
1741  sizeof (r->src_ip_addr.ip6));
1742  else
1743  memcpy (rules[i].src_ip_addr, &r->src_ip_addr.ip4,
1744  sizeof (r->src_ip_addr.ip4));
1745  rules[i].src_ip_prefix_len = r->src_prefixlen;
1746  }
1747  }
1748  else
1749  {
1750  /* No martini, no party - no ACL applied to this interface. */
1751  mp->acl_index = ~0;
1752  mp->count = 0;
1753  }
1754 
1755  vl_msg_api_send_shmem (q, (u8 *) & mp);
1756 }
1757 
1758 
1759 static void
1761 {
1762  acl_main_t *am = &acl_main;
1763  macip_acl_list_t *acl;
1764 
1766 
1768  if (q == 0)
1769  {
1770  return;
1771  }
1772 
1773  if (mp->acl_index == ~0)
1774  {
1775  /* Just dump all ACLs for now, with sw_if_index = ~0 */
1776  pool_foreach (acl, am->macip_acls, (
1777  {
1778  send_macip_acl_details (am, q, acl,
1779  mp->
1780  context);}
1781  ));
1782  /* *INDENT-ON* */
1783  }
1784  else
1785  {
1786  u32 acl_index = ntohl (mp->acl_index);
1787  if (!pool_is_free_index (am->macip_acls, acl_index))
1788  {
1789  acl = pool_elt_at_index (am->macip_acls, acl_index);
1790  send_macip_acl_details (am, q, acl, mp->context);
1791  }
1792  }
1793 }
1794 
1795 static void
1797  mp)
1798 {
1799  acl_main_t *am = &acl_main;
1802  int msg_size = sizeof (*rmp) + sizeof (rmp->acls[0]) * count;
1804  int i;
1805 
1807  if (q == 0)
1808  {
1809  return;
1810  }
1811 
1812  rmp = vl_msg_api_alloc (msg_size);
1813  memset (rmp, 0, msg_size);
1814  rmp->_vl_msg_id =
1815  ntohs (VL_API_MACIP_ACL_INTERFACE_GET_REPLY + am->msg_id_base);
1816  rmp->context = mp->context;
1817  rmp->count = htonl (count);
1818  for (i = 0; i < count; i++)
1819  {
1820  rmp->acls[i] = htonl (am->macip_acl_by_sw_if_index[i]);
1821  }
1822 
1823  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1824 }
1825 
1826 static void
1829  u32 sw_if_index,
1830  u32 acl_index,
1831  u32 context)
1832 {
1834  /* at this time there is only ever 1 mac ip acl per interface */
1835  int msg_size = sizeof (*rmp) + sizeof (rmp->acls[0]);
1836 
1837  rmp = vl_msg_api_alloc (msg_size);
1838  memset (rmp, 0, msg_size);
1839  rmp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_INTERFACE_LIST_DETAILS + am->msg_id_base);
1840 
1841  /* fill in the message */
1842  rmp->context = context;
1843  rmp->count = 1;
1844  rmp->sw_if_index = htonl (sw_if_index);
1845  rmp->acls[0] = htonl (acl_index);
1846 
1847  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1848 }
1849 
1850 static void
1852 {
1854  acl_main_t *am = &acl_main;
1855  u32 sw_if_index = ntohl (mp->sw_if_index);
1856 
1858  if (q == 0)
1859  {
1860  return;
1861  }
1862 
1863  if (sw_if_index == ~0)
1864  {
1866  {
1867  if (~0 != am->macip_acl_by_sw_if_index[sw_if_index])
1868  {
1869  send_macip_acl_interface_list_details(am, q, sw_if_index,
1870  am->macip_acl_by_sw_if_index[sw_if_index],
1871  mp->context);
1872  }
1873  }
1874  }
1875  else
1876  {
1877  if (vec_len(am->macip_acl_by_sw_if_index) > sw_if_index)
1878  {
1879  send_macip_acl_interface_list_details(am, q, sw_if_index,
1880  am->macip_acl_by_sw_if_index[sw_if_index],
1881  mp->context);
1882  }
1883  }
1884 }
1885 
1886 /* Set up the API message handling tables */
1887 static clib_error_t *
1889 {
1890  acl_main_t *am = &acl_main;
1891 #define _(N,n) \
1892  vl_msg_api_set_handlers((VL_API_##N + am->msg_id_base), \
1893  #n, \
1894  vl_api_##n##_t_handler, \
1895  vl_noop_handler, \
1896  vl_api_##n##_t_endian, \
1897  vl_api_##n##_t_print, \
1898  sizeof(vl_api_##n##_t), 1);
1900 #undef _
1901 
1902  return 0;
1903 }
1904 
1905 #define vl_msg_name_crc_list
1906 #include <acl/acl_all_api_h.h>
1907 #undef vl_msg_name_crc_list
1908 
1909 static void
1911 {
1912 #define _(id,n,crc) \
1913  vl_msg_api_add_msg_name_crc (apim, #n "_" #crc, id + am->msg_id_base);
1914  foreach_vl_msg_name_crc_acl;
1915 #undef _
1916 }
1917 
1918 static void
1920 {
1922  acl_main_t *am = &acl_main;
1923  vlib_node_t *n, *n4, *n6;
1924 
1925  n = vlib_get_node_by_name (vm, (u8 *) "l2-input-classify");
1926  n4 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-in-ip4-l2");
1927  n6 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-in-ip6-l2");
1928 
1929 
1931  vlib_node_add_next_with_slot (vm, n->index, n4->index, ~0);
1933  vlib_node_add_next_with_slot (vm, n->index, n6->index, ~0);
1934 
1938 
1942 
1943 
1944  n = vlib_get_node_by_name (vm, (u8 *) "l2-output-classify");
1945  n4 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-out-ip4-l2");
1946  n6 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-out-ip6-l2");
1947 
1949  vlib_node_add_next_with_slot (vm, n->index, n4->index, ~0);
1951  vlib_node_add_next_with_slot (vm, n->index, n6->index, ~0);
1952 
1956 
1960 }
1961 
1962 static void
1963 acl_set_timeout_sec(int timeout_type, u32 value)
1964 {
1965  acl_main_t *am = &acl_main;
1966  clib_time_t *ct = &am->vlib_main->clib_time;
1967 
1968  if (timeout_type < ACL_N_TIMEOUTS) {
1969  am->session_timeout_sec[timeout_type] = value;
1970  } else {
1971  clib_warning("Unknown timeout type %d", timeout_type);
1972  return;
1973  }
1974  am->session_timeout[timeout_type] = (u64)(((f64)value)/ct->seconds_per_clock);
1975 }
1976 
1977 static void
1979 {
1980  acl_main_t *am = &acl_main;
1981  am->fa_conn_table_max_entries = value;
1982 }
1983 
1984 static int
1986 {
1987  acl_main_t *am = &acl_main;
1988 
1989  if ((eh < 256) && (value < 2))
1990  {
1992  return 1;
1993  }
1994  else
1995  return 0;
1996 }
1997 
1998 
1999 static clib_error_t *
2000 acl_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
2001 {
2002  acl_main_t *am = &acl_main;
2003  if (0 == am->acl_mheap) {
2004  /* ACL heap is not initialized, so definitely nothing to do. */
2005  return 0;
2006  }
2007  if (0 == is_add) {
2010  /* also unapply any ACLs in case the users did not do so. */
2011  macip_acl_interface_del_acl(am, sw_if_index);
2012  acl_interface_reset_inout_acls (sw_if_index, 0);
2013  acl_interface_reset_inout_acls (sw_if_index, 1);
2014  }
2015  return 0;
2016 }
2017 
2019 
2020 
2021 
2022 static clib_error_t *
2024  unformat_input_t * input,
2025  vlib_cli_command_t * cmd)
2026 {
2027  clib_error_t *error = 0;
2028  u32 timeout = 0;
2029  u32 val = 0;
2030  u32 eh_val = 0;
2031  uword memory_size = 0;
2032  acl_main_t *am = &acl_main;
2033 
2034  if (unformat (input, "skip-ipv6-extension-header %u %u", &eh_val, &val)) {
2035  if(!acl_set_skip_ipv6_eh(eh_val, val)) {
2036  error = clib_error_return(0, "expecting eh=0..255, value=0..1");
2037  }
2038  goto done;
2039  }
2040  if (unformat (input, "use-hash-acl-matching %u", &val))
2041  {
2042  am->use_hash_acl_matching = (val !=0);
2043  goto done;
2044  }
2045  if (unformat (input, "l4-match-nonfirst-fragment %u", &val))
2046  {
2047  am->l4_match_nonfirst_fragment = (val != 0);
2048  goto done;
2049  }
2050  if (unformat (input, "heap"))
2051  {
2052  if (unformat(input, "main"))
2053  {
2054  if (unformat(input, "validate %u", &val))
2056  else if (unformat(input, "trace %u", &val))
2058  goto done;
2059  }
2060  else if (unformat(input, "hash"))
2061  {
2062  if (unformat(input, "validate %u", &val))
2064  else if (unformat(input, "trace %u", &val))
2066  goto done;
2067  }
2068  goto done;
2069  }
2070  if (unformat (input, "session")) {
2071  if (unformat (input, "table")) {
2072  /* The commands here are for tuning/testing. No user-serviceable parts inside */
2073  if (unformat (input, "max-entries")) {
2074  if (!unformat(input, "%u", &val)) {
2075  error = clib_error_return(0,
2076  "expecting maximum number of entries, got `%U`",
2077  format_unformat_error, input);
2078  goto done;
2079  } else {
2081  goto done;
2082  }
2083  }
2084  if (unformat (input, "hash-table-buckets")) {
2085  if (!unformat(input, "%u", &val)) {
2086  error = clib_error_return(0,
2087  "expecting maximum number of hash table buckets, got `%U`",
2088  format_unformat_error, input);
2089  goto done;
2090  } else {
2092  goto done;
2093  }
2094  }
2095  if (unformat (input, "hash-table-memory")) {
2096  if (!unformat(input, "%U", unformat_memory_size, &memory_size)) {
2097  error = clib_error_return(0,
2098  "expecting maximum amount of hash table memory, got `%U`",
2099  format_unformat_error, input);
2100  goto done;
2101  } else {
2103  goto done;
2104  }
2105  }
2106  goto done;
2107  }
2108  if (unformat (input, "timeout")) {
2109  if (unformat(input, "udp")) {
2110  if(unformat(input, "idle")) {
2111  if (!unformat(input, "%u", &timeout)) {
2112  error = clib_error_return(0,
2113  "expecting timeout value in seconds, got `%U`",
2114  format_unformat_error, input);
2115  goto done;
2116  } else {
2118  goto done;
2119  }
2120  }
2121  }
2122  if (unformat(input, "tcp")) {
2123  if(unformat(input, "idle")) {
2124  if (!unformat(input, "%u", &timeout)) {
2125  error = clib_error_return(0,
2126  "expecting timeout value in seconds, got `%U`",
2127  format_unformat_error, input);
2128  goto done;
2129  } else {
2131  goto done;
2132  }
2133  }
2134  if(unformat(input, "transient")) {
2135  if (!unformat(input, "%u", &timeout)) {
2136  error = clib_error_return(0,
2137  "expecting timeout value in seconds, got `%U`",
2138  format_unformat_error, input);
2139  goto done;
2140  } else {
2142  goto done;
2143  }
2144  }
2145  }
2146  goto done;
2147  }
2148  }
2149 done:
2150  return error;
2151 }
2152 
2153 static u8 *
2154 my_format_mac_address (u8 * s, va_list * args)
2155 {
2156  u8 *a = va_arg (*args, u8 *);
2157  return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
2158  a[0], a[1], a[2], a[3], a[4], a[5]);
2159 }
2160 
2161 static inline u8 *
2163 {
2164  macip_acl_rule_t *a = va_arg (*args, macip_acl_rule_t *);
2165 
2166  out = format(out, "%s action %d ip %U/%d mac %U mask %U",
2167  a->is_ipv6 ? "ipv6" : "ipv4", a->is_permit,
2169  a->src_prefixlen,
2172  return(out);
2173 }
2174 
2175 static void
2176 macip_acl_print(acl_main_t *am, u32 macip_acl_index)
2177 {
2178  vlib_main_t * vm = am->vlib_main;
2179  int i;
2180 
2181  /* Don't try to print someone else's memory */
2182  if (macip_acl_index > vec_len(am->macip_acls))
2183  return;
2184 
2185  macip_acl_list_t *a = vec_elt_at_index(am->macip_acls, macip_acl_index);
2186  int free_pool_slot = pool_is_free_index(am->macip_acls, macip_acl_index);
2187 
2188  vlib_cli_output(vm, "MACIP acl_index: %d, count: %d (true len %d) tag {%s} is free pool slot: %d\n",
2189  macip_acl_index, a->count, vec_len(a->rules), a->tag, free_pool_slot);
2190  vlib_cli_output(vm, " ip4_table_index %d, ip6_table_index %d, l2_table_index %d\n",
2192  for(i=0; i<vec_len(a->rules); i++)
2193  vlib_cli_output(vm, " rule %d: %U\n", i, my_macip_acl_rule_t_pretty_format,
2194  vec_elt_at_index(a->rules, i));
2195 
2196 }
2197 
2198 static clib_error_t *
2200  unformat_input_t * input,
2201  vlib_cli_command_t * cmd)
2202 {
2203  clib_error_t *error = 0;
2204  acl_main_t *am = &acl_main;
2205  int i;
2206  if (unformat (input, "interface"))
2207  {
2208  for(i=0; i < vec_len(am->macip_acl_by_sw_if_index); i++)
2209  {
2210  vlib_cli_output(vm, " sw_if_index %d: %d\n", i, vec_elt(am->macip_acl_by_sw_if_index, i));
2211  }
2212  }
2213  else if (unformat (input, "acl"))
2214  {
2215  for(i=0; i < vec_len(am->macip_acls); i++)
2216  macip_acl_print(am, i);
2217  }
2218  return error;
2219 }
2220 
2221 
2222 static clib_error_t *
2224  unformat_input_t * input,
2225  vlib_cli_command_t * cmd)
2226 {
2227  clib_error_t *error = 0;
2228  acl_main_t *am = &acl_main;
2230  u32 *pj;
2231 
2232  vnet_sw_interface_t *swif;
2233 
2234  if (unformat (input, "sessions"))
2235  {
2236  u8 * out0 = format(0, "");
2237  u16 wk;
2238  u32 show_bihash_verbose = 0;
2239  u32 show_session_thread_id = ~0;
2240  u32 show_session_session_index = ~0;
2241  unformat (input, "thread %u index %u", &show_session_thread_id, &show_session_session_index);
2242  unformat (input, "verbose %u", &show_bihash_verbose);
2243  {
2244  u64 n_adds = am->fa_session_total_adds;
2245  u64 n_dels = am->fa_session_total_dels;
2246  out0 = format(out0, "Sessions total: add %lu - del %lu = %lu\n", n_adds, n_dels, n_adds - n_dels);
2247  }
2248  out0 = format(out0, "\n\nPer-thread data:\n");
2249  for (wk = 0; wk < vec_len (am->per_worker_data); wk++) {
2251  out0 = format(out0, "Thread #%d:\n", wk);
2252  if (show_session_thread_id == wk && show_session_session_index < pool_len(pw->fa_sessions_pool)) {
2253  out0 = format(out0, " session index %u:\n", show_session_session_index);
2254  fa_session_t *sess = pw->fa_sessions_pool + show_session_session_index;
2255  u64 *m = (u64 *)&sess->info;
2256  out0 = format(out0, " info: %016llx %016llx %016llx %016llx %016llx %016llx\n", m[0], m[1], m[2], m[3], m[4], m[5]);
2257  out0 = format(out0, " sw_if_index: %u\n", sess->sw_if_index);
2258  out0 = format(out0, " tcp_flags_seen: %x\n", sess->tcp_flags_seen.as_u16);
2259  out0 = format(out0, " last active time: %lu\n", sess->last_active_time);
2260  out0 = format(out0, " thread index: %u\n", sess->thread_index);
2261  out0 = format(out0, " link enqueue time: %lu\n", sess->link_enqueue_time);
2262  out0 = format(out0, " link next index: %u\n", sess->link_next_idx);
2263  out0 = format(out0, " link prev index: %u\n", sess->link_prev_idx);
2264  out0 = format(out0, " link list id: %u\n", sess->link_list_id);
2265  }
2266  out0 = format(out0, " connection add/del stats:\n", wk);
2267  pool_foreach (swif, im->sw_interfaces,
2268  ({
2269  u32 sw_if_index = swif->sw_if_index;
2270  u64 n_adds = sw_if_index < vec_len(pw->fa_session_adds_by_sw_if_index) ? pw->fa_session_adds_by_sw_if_index[sw_if_index] : 0;
2271  u64 n_dels = sw_if_index < vec_len(pw->fa_session_dels_by_sw_if_index) ? pw->fa_session_dels_by_sw_if_index[sw_if_index] : 0;
2272  out0 = format(out0, " sw_if_index %d: add %lu - del %lu = %lu\n", sw_if_index, n_adds, n_dels, n_adds - n_dels);
2273  }));
2274 
2275  out0 = format(out0, " connection timeout type lists:\n", wk);
2276  u8 tt = 0;
2277  for(tt = 0; tt < ACL_N_TIMEOUTS; tt++) {
2278  u32 head_session_index = pw->fa_conn_list_head[tt];
2279  out0 = format(out0, " fa_conn_list_head[%d]: %d\n", tt, head_session_index);
2280  if (~0 != head_session_index) {
2281  fa_session_t *sess = pw->fa_sessions_pool + head_session_index;
2282  out0 = format(out0, " last active time: %lu\n", sess->last_active_time);
2283  out0 = format(out0, " link enqueue time: %lu\n", sess->link_enqueue_time);
2284  }
2285  }
2286 
2287  out0 = format(out0, " Next expiry time: %lu\n", pw->next_expiry_time);
2288  out0 = format(out0, " Requeue until time: %lu\n", pw->requeue_until_time);
2289  out0 = format(out0, " Current time wait interval: %lu\n", pw->current_time_wait_interval);
2290  out0 = format(out0, " Count of deleted sessions: %lu\n", pw->cnt_deleted_sessions);
2291  out0 = format(out0, " Delete already deleted: %lu\n", pw->cnt_already_deleted_sessions);
2292  out0 = format(out0, " Session timers restarted: %lu\n", pw->cnt_session_timer_restarted);
2293  out0 = format(out0, " Swipe until this time: %lu\n", pw->swipe_end_time);
2294  out0 = format(out0, " sw_if_index serviced bitmap: %U\n", format_bitmap_hex, pw->serviced_sw_if_index_bitmap);
2295  out0 = format(out0, " pending clear intfc bitmap : %U\n", format_bitmap_hex, pw->pending_clear_sw_if_index_bitmap);
2296  out0 = format(out0, " clear in progress: %u\n", pw->clear_in_process);
2297  out0 = format(out0, " interrupt is pending: %d\n", pw->interrupt_is_pending);
2298  out0 = format(out0, " interrupt is needed: %d\n", pw->interrupt_is_needed);
2299  out0 = format(out0, " interrupt is unwanted: %d\n", pw->interrupt_is_unwanted);
2300  out0 = format(out0, " interrupt generation: %d\n", pw->interrupt_generation);
2301  }
2302  out0 = format(out0, "\n\nConn cleaner thread counters:\n");
2303 #define _(cnt, desc) out0 = format(out0, " %20lu: %s\n", am->cnt, desc);
2305 #undef _
2306  vec_terminate_c_string(out0);
2307  vlib_cli_output(vm, "\n\n%s\n\n", out0);
2308  vlib_cli_output(vm, "Interrupt generation: %d\n", am->fa_interrupt_generation);
2309  vlib_cli_output(vm, "Sessions per interval: min %lu max %lu increment: %f ms current: %f ms",
2312 
2313  vec_free(out0);
2314  show_fa_sessions_hash(vm, show_bihash_verbose);
2315  }
2316  else if (unformat (input, "interface"))
2317  {
2318  u32 sw_if_index = ~0;
2319  u32 swi;
2320  u8 * out0 = format(0, "");
2321  unformat (input, "sw_if_index %u", &sw_if_index);
2322  for(swi = 0; (swi < vec_len(am->input_acl_vec_by_sw_if_index)) ||
2323  (swi < vec_len(am->output_acl_vec_by_sw_if_index)); swi++) {
2324  out0 = format(out0, "sw_if_index %d:\n", swi);
2325 
2326  if ((swi < vec_len(am->input_acl_vec_by_sw_if_index)) &&
2327  (vec_len(am->input_acl_vec_by_sw_if_index[swi]) > 0)) {
2328  out0 = format(out0, " input acl(s): ");
2330  out0 = format(out0, "%d ", *pj);
2331  }
2332  out0 = format(out0, "\n");
2333  }
2334 
2335  if ((swi < vec_len(am->output_acl_vec_by_sw_if_index)) &&
2336  (vec_len(am->output_acl_vec_by_sw_if_index[swi]) > 0)) {
2337  out0 = format(out0, " output acl(s): ");
2339  out0 = format(out0, "%d ", *pj);
2340  }
2341  out0 = format(out0, "\n");
2342  }
2343 
2344  }
2345  vec_terminate_c_string(out0);
2346  vlib_cli_output(vm, "\n%s\n", out0);
2347  vec_free(out0);
2348  }
2349  else if (unformat (input, "acl"))
2350  {
2351  u32 acl_index = ~0;
2352  u32 i;
2353  u8 * out0 = format(0, "");
2354  unformat (input, "index %u", &acl_index);
2355  for(i=0; i<vec_len(am->acls); i++) {
2356  if (acl_is_not_defined(am, i)) {
2357  /* don't attempt to show the ACLs that do not exist */
2358  continue;
2359  }
2360  if ((acl_index != ~0) && (acl_index != i)) {
2361  continue;
2362  }
2363  out0 = format(out0, "acl-index %u count %u tag {%s}\n", i, am->acls[i].count, am->acls[i].tag);
2364  acl_rule_t *r;
2365  int j;
2366  for(j=0; j<am->acls[i].count; j++) {
2367  r = &am->acls[i].rules[j];
2368  out0 = format(out0, " %4d: %s ", j, r->is_ipv6 ? "ipv6" : "ipv4");
2369  out0 = format_acl_action(out0, r->is_permit);
2370  out0 = format(out0, " src %U/%d", format_ip46_address, &r->src, IP46_TYPE_ANY, r->src_prefixlen);
2371  out0 = format(out0, " dst %U/%d", format_ip46_address, &r->dst, IP46_TYPE_ANY, r->dst_prefixlen);
2372  out0 = format(out0, " proto %d", r->proto);
2373  out0 = format(out0, " sport %d", r->src_port_or_type_first);
2375  out0 = format(out0, "-%d", r->src_port_or_type_last);
2376  }
2377  out0 = format(out0, " dport %d", r->dst_port_or_code_first);
2379  out0 = format(out0, "-%d", r->dst_port_or_code_last);
2380  }
2381  if (r->tcp_flags_mask || r->tcp_flags_value) {
2382  out0 = format(out0, " tcpflags %d mask %d", r->tcp_flags_value, r->tcp_flags_mask);
2383  }
2384  out0 = format(out0, "\n");
2385  }
2386 
2388  out0 = format(out0, " applied inbound on sw_if_index: ");
2390  out0 = format(out0, "%d ", *pj);
2391  }
2392  out0 = format(out0, "\n");
2393  }
2395  out0 = format(out0, " applied outbound on sw_if_index: ");
2397  out0 = format(out0, "%d ", *pj);
2398  }
2399  out0 = format(out0, "\n");
2400  }
2401  }
2402  vec_terminate_c_string(out0);
2403  vlib_cli_output(vm, "\n%s\n", out0);
2404  vec_free(out0);
2405  }
2406  else if (unformat (input, "memory"))
2407  {
2408  vlib_cli_output (vm, "ACL plugin main heap statistics:\n");
2409  if (am->acl_mheap) {
2410  vlib_cli_output (vm, " %U\n", format_mheap, am->acl_mheap, 1);
2411  } else {
2412  vlib_cli_output (vm, " Not initialized\n");
2413  }
2414  vlib_cli_output (vm, "ACL hash lookup support heap statistics:\n");
2415  if (am->hash_lookup_mheap) {
2416  vlib_cli_output (vm, " %U\n", format_mheap, am->hash_lookup_mheap, 1);
2417  } else {
2418  vlib_cli_output (vm, " Not initialized\n");
2419  }
2420  }
2421  else if (unformat (input, "tables"))
2422  {
2423  ace_mask_type_entry_t *mte;
2424  u32 acl_index = ~0;
2425  u32 sw_if_index = ~0;
2426  int show_acl_hash_info = 0;
2427  int show_applied_info = 0;
2428  int show_mask_type = 0;
2429  int show_bihash = 0;
2430  u32 show_bihash_verbose = 0;
2431 
2432  if (unformat (input, "acl")) {
2433  show_acl_hash_info = 1;
2434  /* mask-type is handy to see as well right there */
2435  show_mask_type = 1;
2436  unformat (input, "index %u", &acl_index);
2437  } else if (unformat (input, "applied")) {
2438  show_applied_info = 1;
2439  unformat (input, "sw_if_index %u", &sw_if_index);
2440  } else if (unformat (input, "mask")) {
2441  show_mask_type = 1;
2442  } else if (unformat (input, "hash")) {
2443  show_bihash = 1;
2444  unformat (input, "verbose %u", &show_bihash_verbose);
2445  }
2446 
2447  if ( ! (show_mask_type || show_acl_hash_info || show_applied_info || show_bihash) ) {
2448  /* if no qualifiers specified, show all */
2449  show_mask_type = 1;
2450  show_acl_hash_info = 1;
2451  show_applied_info = 1;
2452  show_bihash = 1;
2453  }
2454 
2455  if (show_mask_type) {
2456  vlib_cli_output(vm, "Mask-type entries:");
2457  /* *INDENT-OFF* */
2459  ({
2460  vlib_cli_output(vm, " %3d: %016llx %016llx %016llx %016llx %016llx %016llx refcount %d",
2461  mte - am->ace_mask_type_pool,
2462  mte->mask.kv.key[0], mte->mask.kv.key[1], mte->mask.kv.key[2],
2463  mte->mask.kv.key[3], mte->mask.kv.key[4], mte->mask.kv.value, mte->refcount);
2464  }));
2465  /* *INDENT-ON* */
2466  }
2467 
2468  if (show_acl_hash_info) {
2469  u32 i,j;
2470  u8 * out0 = format(0, "");
2471  u64 *m;
2472  out0 = format(out0, "Mask-ready ACL representations\n");
2473  for (i=0; i< vec_len(am->hash_acl_infos); i++) {
2474  if ((acl_index != ~0) && (acl_index != i)) {
2475  continue;
2476  }
2477  hash_acl_info_t *ha = &am->hash_acl_infos[i];
2478  out0 = format(out0, "acl-index %u bitmask-ready layout\n", i);
2479  out0 = format(out0, " applied inbound on sw_if_index list: %U\n", format_vec32, ha->inbound_sw_if_index_list, "%d");
2480  out0 = format(out0, " applied outbound on sw_if_index list: %U\n", format_vec32, ha->outbound_sw_if_index_list, "%d");
2481  out0 = format(out0, " mask type index bitmap: %U\n", format_bitmap_hex, ha->mask_type_index_bitmap);
2482  for(j=0; j<vec_len(ha->rules); j++) {
2483  hash_ace_info_t *pa = &ha->rules[j];
2484  m = (u64 *)&pa->match;
2485  out0 = format(out0, " %4d: %016llx %016llx %016llx %016llx %016llx %016llx mask index %d acl %d rule %d action %d src/dst portrange not ^2: %d,%d\n",
2486  j, m[0], m[1], m[2], m[3], m[4], m[5], pa->mask_type_index,
2487  pa->acl_index, pa->ace_index, pa->action,
2489  }
2490  }
2491  vec_terminate_c_string(out0);
2492  vlib_cli_output(vm, "\n%s\n", out0);
2493  vec_free(out0);
2494  }
2495 
2496  if (show_applied_info) {
2497  u32 swi, j;
2498  u8 * out0 = format(0, "");
2499  out0 = format(out0, "Applied lookup entries for interfaces\n");
2500 
2501  for(swi = 0; (swi < vec_len(am->input_applied_hash_acl_info_by_sw_if_index)) ||
2504  (swi < vec_len(am->output_hash_entry_vec_by_sw_if_index)); swi++) {
2505  if ((sw_if_index != ~0) && (sw_if_index != swi)) {
2506  continue;
2507  }
2508  out0 = format(out0, "sw_if_index %d:\n", swi);
2511  out0 = format(out0, " input lookup mask_type_index_bitmap: %U\n", format_bitmap_hex, pal->mask_type_index_bitmap);
2512  out0 = format(out0, " input applied acls: %U\n", format_vec32, pal->applied_acls, "%d");
2513  }
2515  out0 = format(out0, " input lookup applied entries:\n");
2516  for(j=0; j<vec_len(am->input_hash_entry_vec_by_sw_if_index[swi]); j++) {
2518  out0 = format(out0, " %4d: acl %d rule %d action %d bitmask-ready rule %d next %d prev %d tail %d hitcount %lld\n",
2519  j, pae->acl_index, pae->ace_index, pae->action, pae->hash_ace_info_index,
2521  }
2522  }
2523 
2526  out0 = format(out0, " output lookup mask_type_index_bitmap: %U\n", format_bitmap_hex, pal->mask_type_index_bitmap);
2527  out0 = format(out0, " output applied acls: %U\n", format_vec32, pal->applied_acls, "%d");
2528  }
2530  out0 = format(out0, " output lookup applied entries:\n");
2531  for(j=0; j<vec_len(am->output_hash_entry_vec_by_sw_if_index[swi]); j++) {
2533  out0 = format(out0, " %4d: acl %d rule %d action %d bitmask-ready rule %d next %d prev %d tail %d hitcount %lld\n",
2534  j, pae->acl_index, pae->ace_index, pae->action, pae->hash_ace_info_index,
2536  }
2537  }
2538 
2539  }
2540  vec_terminate_c_string(out0);
2541  vlib_cli_output(vm, "\n%s\n", out0);
2542  vec_free(out0);
2543  }
2544 
2545  if (show_bihash) {
2546  show_hash_acl_hash(vm, am, show_bihash_verbose);
2547  }
2548  }
2549  return error;
2550 }
2551 
2552 static clib_error_t *
2554  unformat_input_t * input,
2555  vlib_cli_command_t * cmd)
2556 {
2557  clib_error_t *error = 0;
2558  acl_main_t *am = &acl_main;
2561  return error;
2562 }
2563 
2564  /* *INDENT-OFF* */
2565 VLIB_CLI_COMMAND (aclplugin_set_command, static) = {
2566  .path = "set acl-plugin",
2567  .short_help = "set acl-plugin session timeout {{udp idle}|tcp {idle|transient}} <seconds>",
2568  .function = acl_set_aclplugin_fn,
2569 };
2570 
2571 VLIB_CLI_COMMAND (aclplugin_show_command, static) = {
2572  .path = "show acl-plugin",
2573  .short_help = "show acl-plugin {sessions|acl|interface|tables}",
2574  .function = acl_show_aclplugin_fn,
2575 };
2576 
2577 VLIB_CLI_COMMAND (aclplugin_show_macip_command, static) = {
2578  .path = "show acl-plugin macip",
2579  .short_help = "show acl-plugin macip {acl|interface}",
2580  .function = acl_show_aclplugin_macip_fn,
2581 };
2582 
2583 
2584 VLIB_CLI_COMMAND (aclplugin_clear_command, static) = {
2585  .path = "clear acl-plugin sessions",
2586  .short_help = "clear acl-plugin sessions",
2587  .function = acl_clear_aclplugin_fn,
2588 };
2589 /* *INDENT-ON* */
2590 
2591 static clib_error_t *
2593 {
2594  acl_main_t *am = &acl_main;
2595  u32 conn_table_hash_buckets;
2596  u32 conn_table_hash_memory_size;
2597  u32 conn_table_max_entries;
2598  u32 main_heap_size;
2599  u32 hash_heap_size;
2600  u32 hash_lookup_hash_buckets;
2601  u32 hash_lookup_hash_memory;
2602 
2603  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2604  {
2605  if (unformat (input, "connection hash buckets %d", &conn_table_hash_buckets))
2606  am->fa_conn_table_hash_num_buckets = conn_table_hash_buckets;
2607  else if (unformat (input, "connection hash memory %d",
2608  &conn_table_hash_memory_size))
2609  am->fa_conn_table_hash_memory_size = conn_table_hash_memory_size;
2610  else if (unformat (input, "connection count max %d",
2611  &conn_table_max_entries))
2612  am->fa_conn_table_max_entries = conn_table_max_entries;
2613  else if (unformat (input, "main heap size %d",
2614  &main_heap_size))
2615  am->acl_mheap_size = main_heap_size;
2616  else if (unformat (input, "hash lookup heap size %d",
2617  &hash_heap_size))
2618  am->hash_lookup_mheap_size = hash_heap_size;
2619  else if (unformat (input, "hash lookup hash buckets %d",
2620  &hash_lookup_hash_buckets))
2621  am->hash_lookup_hash_buckets = hash_lookup_hash_buckets;
2622  else if (unformat (input, "hash lookup hash memory %d",
2623  &hash_lookup_hash_memory))
2624  am->hash_lookup_hash_memory = hash_lookup_hash_memory;
2625  else
2626  return clib_error_return (0, "unknown input '%U'",
2627  format_unformat_error, input);
2628  }
2629  return 0;
2630 }
2631 VLIB_CONFIG_FUNCTION (acl_plugin_config, "acl-plugin");
2632 
2633 static clib_error_t *
2635 {
2636  acl_main_t *am = &acl_main;
2637  clib_error_t *error = 0;
2638  memset (am, 0, sizeof (*am));
2639  am->vlib_main = vm;
2640  am->vnet_main = vnet_get_main ();
2641 
2642  u8 *name = format (0, "acl_%08x%c", api_version, 0);
2643 
2644  /* Ask for a correctly-sized block of API message decode slots */
2645  am->msg_id_base = vl_msg_api_get_msg_ids ((char *) name,
2647 
2648  error = acl_plugin_api_hookup (vm);
2649 
2650  /* Add our API messages to the global name_crc hash table */
2652 
2653  vec_free (name);
2654 
2656 
2659 
2662 
2666 
2672  {
2673  u16 wk;
2674  u8 tt;
2675  for (wk = 0; wk < vec_len (am->per_worker_data); wk++) {
2679  for(tt = 0; tt < ACL_N_TIMEOUTS; tt++) {
2680  pw->fa_conn_list_head[tt] = ~0;
2681  pw->fa_conn_list_tail[tt] = ~0;
2682  }
2683  }
2684  }
2685 
2689 
2690  am->fa_cleaner_cnt_delete_by_sw_index = 0;
2691  am->fa_cleaner_cnt_delete_by_sw_index_ok = 0;
2692  am->fa_cleaner_cnt_unknown_event = 0;
2693  am->fa_cleaner_cnt_timer_restarted = 0;
2694  am->fa_cleaner_cnt_wait_with_timeout = 0;
2695 
2696 
2697 #define _(N, v, s) am->fa_ipv6_known_eh_bitmap = clib_bitmap_set(am->fa_ipv6_known_eh_bitmap, v, 1);
2699 #undef _
2700 
2702 
2703  /* use the new fancy hash-based matching */
2704  am->use_hash_acl_matching = 1;
2705 
2706  return error;
2707 }
2708 
acl_rule_t * rules
Definition: acl.h:107
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:432
macip_acl_rule_t * rules
Definition: acl.h:114
u32 * acl_ip4_output_classify_table_by_sw_if_index
Definition: acl.h:179
static int macip_acl_interface_add_acl(acl_main_t *am, u32 sw_if_index, u32 macip_acl_index)
Definition: acl.c:1248
u8 src_mac[6]
Definition: acl.h:94
u32 fa_cleaner_node_index
Definition: acl.h:192
u32 session_timeout_sec[ACL_N_TIMEOUTS]
Definition: acl.h:194
static u8 * format_bitmap_hex(u8 *s, va_list *args)
Format a bitmap as a string of hex bytes.
Definition: bitmap.h:744
Use acl_interface_set_acl_list instead Append/remove an ACL index to/from the list of ACLs checked fo...
Definition: acl.api:206
#define vec_foreach_index(var, v)
Iterate over vector indices.
u32 fa_acl_in_ip4_l2_node_feat_next_node_index[32]
Definition: acl.h:207
static int macip_acl_interface_add_del_acl(u32 sw_if_index, u8 is_add, u32 acl_list_index)
Definition: acl.c:1310
static clib_error_t * acl_clear_aclplugin_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:2553
static int acl_set_skip_ipv6_eh(u32 eh, u32 value)
Definition: acl.c:1985
static int acl_hook_l2_output_classify(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:591
u16 vl_msg_api_get_msg_ids(const char *name, int n)
Definition: api_shared.c:857
static int verify_message_len(void *mp, u32 expected_len, char *where)
Definition: acl.c:1342
static int acl_classify_add_del_table_tiny(vnet_classify_main_t *cm, u8 *mask, u32 mask_len, u32 next_table_index, u32 miss_next_index, u32 *table_index, int is_add)
Definition: acl.c:393
#define UDP_SESSION_IDLE_TIMEOUT_SEC
Definition: acl.h:36
void acl_plugin_hash_acl_set_trace_heap(acl_main_t *am, int on)
Definition: hash_lookup.c:291
static void send_macip_acl_details(acl_main_t *am, unix_shared_memory_queue_t *q, macip_acl_list_t *acl, u32 context)
Definition: acl.c:1710
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
static clib_error_t * acl_init(vlib_main_t *vm)
Definition: acl.c:2634
static void acl_setup_fa_nodes(void)
Definition: acl.c:1919
static void send_macip_acl_interface_list_details(acl_main_t *am, unix_shared_memory_queue_t *q, u32 sw_if_index, u32 acl_index, u32 context)
Definition: acl.c:1827
void show_fa_sessions_hash(vlib_main_t *vm, u32 verbose)
Definition: fa_node.c:1682
int acl_interface_out_enable_disable(acl_main_t *am, u32 sw_if_index, int enable_disable)
Definition: acl.c:680
u8 is_ipv6
Definition: acl.h:76
char ** l2output_get_feat_names(void)
Definition: l2_output.c:38
static int acl_interface_del_inout_acl(u32 sw_if_index, u8 is_input, u32 acl_list_index)
Definition: acl.c:771
uword * pending_clear_sw_if_index_bitmap
Definition: fa_node.h:134
static void vl_api_acl_plugin_get_version_t_handler(vl_api_acl_plugin_get_version_t *mp)
Definition: acl.c:130
Definition: acl.h:125
a
Definition: bitmap.h:516
int acl_interface_in_enable_disable(acl_main_t *am, u32 sw_if_index, int enable_disable)
Definition: acl.c:655
u64 fa_current_cleaner_timer_wait_interval
Definition: acl.h:242
u32 acl_index
Set the vector of input/output ACLs checked for an interface.
Definition: acl.api:229
static clib_error_t * acl_show_aclplugin_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:2223
#define foreach_acl_plugin_api_msg
Definition: acl.c:64
u32 ** input_acl_vec_by_sw_if_index
Definition: acl.h:157
u16 msg_id_base
Definition: acl.h:137
Dump the list(s) of ACL applied to specific or all interfaces.
Definition: acl.api:280
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
vl_api_macip_acl_rule_t r[count]
Definition: acl.api:318
static int count_skip(u8 *p, u32 size)
Definition: acl.c:378
vnet_interface_main_t interface_main
Definition: vnet.h:56
static void vl_api_acl_add_replace_t_handler(vl_api_acl_add_replace_t *mp)
Definition: acl.c:1356
static void vl_api_macip_acl_dump_t_handler(vl_api_macip_acl_dump_t *mp)
Definition: acl.c:1760
int l4_match_nonfirst_fragment
Definition: acl.h:216
u8 src_ip_addr[16]
Definition: acl.api:91
void * mheap_alloc(void *memory, uword size)
Definition: mheap.c:947
Control ping from the client to the server response.
Definition: acl.api:63
#define ACL_FA_CONN_TABLE_DEFAULT_HASH_NUM_BUCKETS
Definition: fa_node.h:18
#define ACL_PLUGIN_VERSION_MINOR
Definition: acl.h:34
static clib_error_t * acl_plugin_config(vlib_main_t *vm, unformat_input_t *input)
Definition: acl.c:2592
#define ACL_PLUGIN_HASH_LOOKUP_HASH_MEMORY
Definition: acl.h:44
#define REPLY_MACRO2(t, body)
#define NULL
Definition: clib.h:55
u32 index
Definition: node.h:237
static void vl_api_macip_acl_add_t_handler(vl_api_macip_acl_add_t *mp)
Definition: acl.c:1630
f64 clocks_per_second
Definition: time.h:53
u8 dst_prefixlen
Definition: acl.h:80
u8 action
u32 hash_ace_info_index
u32 * acl_ip6_input_classify_table_by_sw_if_index
Definition: acl.h:178
fa_5tuple_t info
Definition: fa_node.h:58
u32 count
Definition: acl.h:106
#define vec_terminate_c_string(V)
(If necessary) NULL terminate a vector containing a c-string.
Definition: vec.h:990
u32 l2_table_index
Definition: acl.h:118
void vnet_l2_input_classify_enable_disable(u32 sw_if_index, int enable_disable)
Enable/disable l2 input classification on a specific interface.
static mheap_t * mheap_header(u8 *v)
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
format_function_t format_ip46_address
Definition: format.h:61
u64 session_timeout[ACL_N_TIMEOUTS]
Definition: acl.h:250
fa_session_t * fa_sessions_pool
Definition: fa_node.h:108
u32 l2_input_classify_next_acl_ip4
Definition: acl.h:202
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
Access List Rule entry.
Definition: acl.api:87
applied_hash_acl_info_t * output_applied_hash_acl_info_by_sw_if_index
Definition: acl.h:152
clib_time_t clib_time
Definition: main.h:62
u8 link_list_id
Definition: fa_node.h:69
u16 dstport_or_icmpcode_last
Definition: acl.api:112
static clib_error_t * acl_show_aclplugin_macip_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:2199
#define MHEAP_FLAG_THREAD_SAFE
Delete a MACIP ACL.
Definition: acl.api:372
u8 * format_mheap(u8 *s, va_list *va)
Definition: mheap.c:1162
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:140
static u32 macip_find_match_type(macip_match_type_t *mv, u8 *mac_mask, u8 prefix_len, u8 is_ipv6)
Definition: acl.c:924
u32 table_index
Definition: acl.c:919
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
Details about one MACIP ACL.
Definition: acl.api:418
u32 fa_acl_out_ip4_l2_node_feat_next_node_index[32]
Definition: acl.h:209
f64 fa_cleaner_wait_time_increment
Definition: acl.h:240
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:595
void hash_acl_add(acl_main_t *am, int acl_index)
Definition: hash_lookup.c:770
uword fa_conn_table_hash_memory_size
Definition: acl.h:220
u16 dst_port_or_code_last
Definition: acl.h:85
static clib_error_t * acl_sw_interface_add_del(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
Definition: acl.c:2000
u8 src_mac_mask[6]
Definition: acl.h:95
u32 l2_output_classify_next_acl_ip4
Definition: acl.h:204
u8 src_prefixlen
Definition: acl.h:78
ip46_address_t src_ip_addr
Definition: acl.h:96
void mv(vnet_classify_table_t *t)
Definition: vnet_classify.c:66
u32 next_applied_entry_index
void acl_plugin_hash_acl_set_validate_heap(acl_main_t *am, int on)
Definition: hash_lookup.c:276
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:437
u32 link_prev_idx
Definition: fa_node.h:67
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
static int acl_is_not_defined(acl_main_t *am, u32 acl_list_index)
Definition: acl.c:705
u16 dstport_or_icmpcode_first
Definition: acl.api:111
u64 fa_conn_table_max_entries
Definition: acl.h:221
vnet_main_t * vnet_main
Definition: acl.h:270
unsigned long long u32x4
Definition: ixge.c:28
ip46_address_t src
Definition: acl.h:77
u8 src_ip_prefix_len
Definition: acl.api:92
u8 tcp_flags_value
Definition: acl.api:119
uword vlib_node_add_next_with_slot(vlib_main_t *vm, uword node_index, uword next_node_index, uword slot)
Definition: node.c:205
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Add or delete a MACIP ACL to/from interface.
Definition: acl.api:387
#define clib_error_return(e, args...)
Definition: error.h:99
static u8 * format_acl_action(u8 *s, u8 action)
Definition: manual_fns.h:105
u8 src_prefixlen
Definition: acl.h:97
u8 is_permit
Definition: acl.h:75
#define ACL_FA_CONN_TABLE_DEFAULT_MAX_ENTRIES
Definition: fa_node.h:20
unsigned long u64
Definition: types.h:89
int vnet_l2_output_classify_set_tables(u32 sw_if_index, u32 ip4_table_index, u32 ip6_table_index, u32 other_table_index)
Set l2 per-protocol, per-interface output classification tables.
u8 mac_mask[6]
Definition: acl.c:916
#define vec_search(v, E)
Search a vector for the index of the entry that matches.
Definition: vec.h:937
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(acl_sw_interface_add_del)
u32 ip4_table_index
Definition: acl.h:116
void hash_acl_unapply(acl_main_t *am, u32 sw_if_index, u8 is_input, int acl_index)
Definition: hash_lookup.c:524
u32 * inbound_sw_if_index_list
void * vl_msg_api_alloc(int nbytes)
Reply to add/replace MACIP ACL.
Definition: acl.api:359
u32 fa_acl_out_ip6_l2_node_feat_next_node_index[32]
Definition: acl.h:210
static u8 * my_macip_acl_rule_t_pretty_format(u8 *out, va_list *args)
Definition: acl.c:2162
u32 * acl_ip4_input_classify_table_by_sw_if_index
Definition: acl.h:177
#define fl(x, y)
ip46_address_t dst
Definition: acl.h:79
uword * mask_type_index_bitmap
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)
static int acl_unhook_l2_input_classify(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:449
applied_hash_acl_info_t * input_applied_hash_acl_info_by_sw_if_index
Definition: acl.h:151
Reply to add MACIP ACL.
Definition: acl.api:327
static int acl_hook_l2_input_classify(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:532
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:458
Details about a single MACIP ACL contents.
Definition: acl.api:471
static void acl_set_session_max_entries(u32 value)
Definition: acl.c:1978
Control ping from client to api server request.
Definition: acl.api:51
static void setup_message_id_table(acl_main_t *am, api_main_t *apim)
Definition: acl.c:1910
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:950
VLIB_PLUGIN_REGISTER()
#define ACL_FA_DEFAULT_CLEANER_WAIT_TIME_INCREMENT
Definition: acl.h:239
u16 dst_port_or_code_first
Definition: acl.h:84
#define TCP_SESSION_IDLE_TIMEOUT_SEC
Definition: acl.h:37
static void vl_api_acl_dump_t_handler(vl_api_acl_dump_t *mp)
Definition: acl.c:1505
#define v
Definition: acl.c:323
struct _unformat_input_t unformat_input_t
uword * fa_ipv6_known_eh_bitmap
Definition: acl.h:213
Replace an existing ACL in-place or create a new ACL.
Definition: acl.api:159
#define ACL_FA_DEFAULT_MIN_DELETED_SESSIONS_PER_INTERVAL
Definition: acl.h:236
hash_acl_info_t * hash_acl_infos
Definition: acl.h:140
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:270
void acl_plugin_acl_set_validate_heap(acl_main_t *am, int on)
Definition: acl.c:103
u64 hitcount
Details about a single ACL contents.
Definition: acl.api:295
union fa_session_t::@287 tcp_flags_seen
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:119
hash_ace_info_t * rules
#define REPLY_MACRO(t)
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:801
vl_api_acl_rule_t r[count]
Definition: acl.api:166
static int get_l3_src_offset(int is6)
Definition: acl.c:975
f64 seconds_per_clock
Definition: time.h:57
void show_hash_acl_hash(vlib_main_t *vm, acl_main_t *am, u32 verbose)
Definition: hash_lookup.c:890
u64 last_active_time
Definition: fa_node.h:59
u32 l2_input_classify_next_acl_ip6
Definition: acl.h:203
u8 proto
Definition: acl.h:81
u8 dst_ip_addr[16]
Definition: acl.api:93
static u8 * my_format_mac_address(u8 *s, va_list *args)
Definition: acl.c:2154
static void send_acl_details(acl_main_t *am, unix_shared_memory_queue_t *q, acl_list_t *acl, u32 context)
Definition: acl.c:1474
u16 src_port_or_type_first
Definition: acl.h:82
u64 fa_min_deleted_sessions_per_interval
Definition: acl.h:237
static int match_type_compare(macip_match_type_t *m1, macip_match_type_t *m2)
Definition: acl.c:967
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:182
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P (general version).
Definition: pool.h:188
vl_api_acl_rule_t r[count]
Definition: acl.api:271
static int acl_unhook_l2_output_classify(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:490
Dump the list(s) of MACIP ACLs applied to specific or all interfaces.
Definition: acl.api:457
static int match_type_metric(macip_match_type_t *m)
Definition: acl.c:946
static int macip_acl_del_list(u32 acl_list_index)
Definition: acl.c:1274
Dump one or all defined MACIP ACLs.
Definition: acl.api:403
api_main_t api_main
Definition: api_shared.c:35
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
static int acl_classify_add_del_table_small(vnet_classify_main_t *cm, u8 *mask, u32 mask_len, u32 next_table_index, u32 miss_next_index, u32 *table_index, int is_add)
Definition: acl.c:420
vlib_main_t * vm
Definition: buffer.c:283
vec_header_t h
Definition: buffer.c:282
applied_hash_ace_entry_t ** output_hash_entry_vec_by_sw_if_index
Definition: acl.h:150
u64 fa_session_total_adds
Definition: acl.h:196
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
void acl_plugin_acl_set_trace_heap(acl_main_t *am, int on)
Definition: acl.c:118
static void feat_bitmap_init_next_nodes(vlib_main_t *vm, u32 node_index, u32 num_features, char **feat_names, u32 *next_nodes)
Initialize the feature next-node indexes of a graph node.
Definition: feat_bitmap.h:43
u32 * outbound_sw_if_index_list
static void * clib_mem_set_heap(void *heap)
Definition: mem.h:226
u16 srcport_or_icmptype_first
Definition: acl.api:109
void hash_acl_delete(acl_main_t *am, int acl_index)
Definition: hash_lookup.c:827
Reply to add/replace ACL.
Definition: acl.api:175
#define clib_warning(format, args...)
Definition: error.h:59
static int acl_interface_add_inout_acl(u32 sw_if_index, u8 is_input, u32 acl_list_index)
Definition: acl.c:712
u64 memory_size
Definition: vhost-user.h:77
Definition: acl.h:73
Reply with the vector of MACIP ACLs by sw_if_index.
Definition: acl.api:444
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
u8 * format_vec32(u8 *s, va_list *va)
Definition: std-formats.c:43
u32 sw_if_index
Definition: fa_node.h:60
int vnet_l2_input_classify_set_tables(u32 sw_if_index, u32 ip4_table_index, u32 ip6_table_index, u32 other_table_index)
Set l2 per-protocol, per-interface input classification tables.
int use_hash_acl_matching
Definition: acl.h:168
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:267
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
#define foreach_fa_cleaner_counter
Definition: acl.h:255
vl_api_macip_acl_rule_t r[count]
Definition: acl.api:350
void acl_fa_enable_disable(u32 sw_if_index, int is_input, int enable_disable)
Definition: fa_node.c:1627
char ** l2input_get_feat_names(void)
Return an array of strings containing graph node names of each feature.
Definition: l2_input.c:60
u8 is_ipv6
Definition: acl.h:93
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:72
u16 srcport_or_icmptype_last
Definition: acl.api:110
#define ACL_PLUGIN_HASH_LOOKUP_HASH_BUCKETS
Definition: acl.h:43
u32 hash_lookup_hash_buckets
Definition: acl.h:142
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
static void vl_api_acl_interface_add_del_t_handler(vl_api_acl_interface_add_del_t *mp)
Definition: acl.c:1392
#define ASSERT(truth)
static int macip_acl_interface_del_acl(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:1223
unsigned int u32
Definition: types.h:88
u8 tag[64]
Definition: acl.h:105
static void vl_api_macip_acl_del_t_handler(vl_api_macip_acl_del_t *mp)
Definition: acl.c:1678
u16 src_port_or_type_last
Definition: acl.h:83
MACIP Access List Rule entry.
Definition: acl.api:131
static int macip_create_classify_tables(acl_main_t *am, u32 macip_acl_index)
Definition: acl.c:984
static void acl_set_timeout_sec(int timeout_type, u32 value)
Definition: acl.c:1963
static void send_acl_interface_list_details(acl_main_t *am, unix_shared_memory_queue_t *q, u32 sw_if_index, u32 context)
Definition: acl.c:1548
u64 size
Definition: vhost-user.h:76
#define ACL_FA_DEFAULT_HEAP_SIZE
Definition: acl.h:40
#define MHEAP_FLAG_VALIDATE
u8 dst_ip_prefix_len
Definition: acl.api:94
acl_main_t acl_main
Definition: acl.c:57
vnet_classify_main_t vnet_classify_main
Definition: vnet_classify.c:22
size_t count
Definition: vapi.c:40
static void vl_api_macip_acl_add_replace_t_handler(vl_api_macip_acl_add_replace_t *mp)
Definition: acl.c:1654
Delete an ACL.
Definition: acl.api:188
Reply to get the plugin version.
Definition: acl.api:40
static clib_error_t * acl_plugin_api_hookup(vlib_main_t *vm)
Definition: acl.c:1888
static int macip_acl_add_list(u32 count, vl_api_macip_acl_rule_t rules[], u32 *acl_list_index, u8 *tag)
Definition: acl.c:1149
uword * serviced_sw_if_index_bitmap
Definition: fa_node.h:132
vl_api_macip_acl_rule_t r[count]
Definition: acl.api:424
u32 fa_acl_in_ip6_l2_node_feat_next_node_index[32]
Definition: acl.h:208
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
Reply to set the ACL list on an interface.
Definition: acl.api:250
u32 link_next_idx
Definition: fa_node.h:68
u64 uword
Definition: types.h:112
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 MHEAP_FLAG_TRACE
#define vec_elt(v, i)
Get vector value at index i.
ace_mask_type_entry_t * ace_mask_type_pool
Definition: acl.h:171
#define MHEAP_FLAG_SMALL_OBJECT_CACHE
static void macip_acl_print(acl_main_t *am, u32 macip_acl_index)
Definition: acl.c:2176
u32 prev_applied_entry_index
u32 * macip_acl_by_sw_if_index
Definition: acl.h:183
Get the vector of MACIP ACL IDs applied to the interfaces.
Definition: acl.api:432
#define XX
Definition: acl.c:320
u32 * acl_ip6_output_classify_table_by_sw_if_index
Definition: acl.h:180
static void vl_api_acl_interface_list_dump_t_handler(vl_api_acl_interface_list_dump_t *mp)
Definition: acl.c:1594
u16 as_u16
Definition: fa_node.h:63
Add/Replace a MACIP ACL.
Definition: acl.api:343
static int acl_add_list(u32 count, vl_api_acl_rule_t rules[], u32 *acl_list_index, u8 *tag)
Definition: acl.c:170
unsigned short u16
Definition: types.h:57
static void vl_api_acl_del_t_handler(vl_api_acl_del_t *mp)
Definition: acl.c:1380
macip_acl_list_t * macip_acls
Definition: acl.h:154
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:142
unsigned char u8
Definition: types.h:56
Details about a single ACL contents.
Definition: acl.api:265
u32 ip6_table_index
Definition: acl.h:117
static void vl_api_macip_acl_interface_list_dump_t_handler(vl_api_macip_acl_interface_list_dump_t *mp)
Definition: acl.c:1851
u8 tcp_flags_mask
Definition: acl.h:87
acl_fa_per_worker_data_t * per_worker_data
Definition: acl.h:247
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:956
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:659
int fa_interrupt_generation
Definition: acl.h:244
u32 ** input_sw_if_index_vec_by_acl
Definition: acl.h:161
void vnet_l2_output_classify_enable_disable(u32 sw_if_index, int enable_disable)
Enable/disable l2 input classification on a specific interface.
static void vl_api_acl_interface_set_acl_list_t_handler(vl_api_acl_interface_set_acl_list_t *mp)
Definition: acl.c:1412
u64 fa_max_deleted_sessions_per_interval
Definition: acl.h:229
void * acl_mheap
Definition: acl.h:133
static clib_error_t * acl_set_aclplugin_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:2023
u16 thread_index
Definition: fa_node.h:64
unformat_function_t unformat_memory_size
Definition: format.h:294
static void acl_interface_reset_inout_acls(u32 sw_if_index, u8 is_input)
Definition: acl.c:840
void hash_acl_apply(acl_main_t *am, u32 sw_if_index, u8 is_input, int acl_index)
Definition: hash_lookup.c:303
static int acl_interface_add_del_inout_acl(u32 sw_if_index, u8 is_add, u8 is_input, u32 acl_list_index)
Definition: acl.c:889
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
u8 tcp_flags_value
Definition: acl.h:86
Get the plugin version.
Definition: acl.api:28
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
static void copy_acl_rule_to_api_rule(vl_api_acl_rule_t *api_rule, acl_rule_t *r)
Definition: acl.c:1448
void mheap_validate(void *v)
Definition: mheap.c:1338
#define vec_foreach(var, vec)
Vector iterator.
static void * acl_set_heap(acl_main_t *am)
Definition: acl.c:91
void * hash_lookup_mheap
Definition: acl.h:146
int vnet_set_input_acl_intfc(vlib_main_t *vm, u32 sw_if_index, u32 ip4_table_index, u32 ip6_table_index, u32 l2_table_index, u32 is_add)
Definition: input_acl.c:59
u32 acl_mheap_size
Definition: acl.h:134
u32 tail_applied_entry_index
Add a MACIP ACL.
Definition: acl.api:312
u32 vl_msg_api_get_msg_length(void *msg_arg)
Definition: api_shared.c:634
u32 client_index
Definition: acl.api:252
u32 ** output_sw_if_index_vec_by_acl
Definition: acl.h:162
#define ACL_PLUGIN_VERSION_MAJOR
Definition: acl.h:33
u8 tag[64]
Definition: acl.h:112
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:481
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
#define ACL_PLUGIN_HASH_LOOKUP_HEAP_SIZE
Definition: acl.h:42
u32 hash_lookup_mheap_size
Definition: acl.h:147
u32 l2_output_classify_next_acl_ip6
Definition: acl.h:205
u8 ip6_5tuple_mask[]
Definition: acl.c:353
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:680
#define ACL_FA_DEFAULT_MAX_DELETED_SESSIONS_PER_INTERVAL
Definition: acl.h:228
static void vl_api_acl_plugin_control_ping_t_handler(vl_api_acl_plugin_control_ping_t *mp)
Definition: acl.c:155
acl_list_t * acls
Definition: acl.h:139
u32 ** output_acl_vec_by_sw_if_index
Definition: acl.h:158
#define TCP_SESSION_TRANSIENT_TIMEOUT_SEC
Definition: acl.h:38
u8 is_permit
Definition: acl.h:92
static void vl_api_macip_acl_interface_add_del_t_handler(vl_api_macip_acl_interface_add_del_t *mp)
Definition: acl.c:1691
u32 hash_lookup_hash_memory
Definition: acl.h:143
u32 ace_index
u32 arp_table_index
Definition: acl.c:920
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
u64 link_enqueue_time
Definition: fa_node.h:66
u32 fa_conn_table_hash_num_buckets
Definition: acl.h:219
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
#define ACL_FA_CONN_TABLE_DEFAULT_HASH_MEMORY_SIZE
Definition: fa_node.h:19
u64 fa_session_total_dels
Definition: acl.h:197
struct _unix_shared_memory_queue unix_shared_memory_queue_t
static int acl_del_list(u32 acl_list_index)
Definition: acl.c:251
static void macip_destroy_classify_tables(acl_main_t *am, u32 macip_acl_index)
Definition: acl.c:1126
static void vl_api_macip_acl_interface_get_t_handler(vl_api_macip_acl_interface_get_t *mp)
Definition: acl.c:1796
applied_hash_ace_entry_t ** input_hash_entry_vec_by_sw_if_index
Definition: acl.h:149
u8 ip4_5tuple_mask[]
Definition: acl.c:325
foreach_fa_cleaner_counter vlib_main_t * vlib_main
Definition: acl.h:269