FD.io VPP  v20.09-64-g4f7b92f0a
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>
25 #include <vpp/app/version.h>
26 
28 
29 #include <vlibapi/api.h>
30 #include <vlibmemory/api.h>
31 
32 /* define message IDs */
33 #include <acl/acl.api_enum.h>
34 #include <acl/acl.api_types.h>
35 
36 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
37 #include "manual_fns.h"
38 
39 #include "fa_node.h"
40 #include "public_inlines.h"
41 
43 
44 #define REPLY_MSG_ID_BASE am->msg_id_base
46 
47 /*
48  * The code for the bihash, used by the session management.
49  */
50 #include <vppinfra/bihash_40_8.h>
53 
54 /* *INDENT-OFF* */
56  .version = VPP_BUILD_VER,
57  .description = "Access Control Lists (ACL)",
58 };
59 /* *INDENT-ON* */
60 
61 /* methods exported from ACL-as-a-service */
63 
64 /* Format vec16. */
65 u8 *
66 format_vec16 (u8 * s, va_list * va)
67 {
68  u16 *v = va_arg (*va, u16 *);
69  char *fmt = va_arg (*va, char *);
70  uword i;
71  for (i = 0; i < vec_len (v); i++)
72  {
73  if (i > 0)
74  s = format (s, ", ");
75  s = format (s, fmt, v[i]);
76  }
77  return s;
78 }
79 
80 static void *
82 {
83  if (0 == am->acl_mheap)
84  {
85  if (0 == am->acl_mheap_size)
86  {
88  u64 per_worker_slack = 1000000LL;
89  u64 per_worker_size =
90  per_worker_slack +
91  ((u64) am->fa_conn_table_max_entries) * sizeof (fa_session_t);
92  u64 per_worker_size_with_slack = per_worker_slack + per_worker_size;
93  u64 main_slack = 2000000LL;
94  u64 bihash_size = (u64) am->fa_conn_table_hash_memory_size;
95 
96  am->acl_mheap_size =
97  per_worker_size_with_slack * tm->n_vlib_mains + bihash_size +
98  main_slack;
99  }
100  u64 max_possible = ((uword) ~ 0);
101  if (am->acl_mheap_size > max_possible)
102  {
103  clib_warning ("ACL heap size requested: %lld, max possible %lld",
104  am->acl_mheap_size, max_possible);
105  }
106 
107  am->acl_mheap = mheap_alloc_with_lock (0 /* use VM */ ,
108  am->acl_mheap_size,
109  1 /* locked */ );
110  if (0 == am->acl_mheap)
111  {
112  clib_error
113  ("ACL plugin failed to allocate main heap of %U bytes, abort",
115  }
116  }
117  void *oldheap = clib_mem_set_heap (am->acl_mheap);
118  return oldheap;
119 }
120 
121 void *
123 {
124  acl_main_t *am = &acl_main;
125  return acl_set_heap (am);
126 }
127 
128 void
130 {
132 }
133 
134 void
136 {
138 }
139 
140 static void
142 {
143  acl_main_t *am = &acl_main;
145  int msg_size = sizeof (*rmp);
147 
149  if (!reg)
150  return;
151 
152  rmp = vl_msg_api_alloc (msg_size);
153  clib_memset (rmp, 0, msg_size);
154  rmp->_vl_msg_id =
155  ntohs (VL_API_ACL_PLUGIN_GET_VERSION_REPLY + am->msg_id_base);
156  rmp->context = mp->context;
157  rmp->major = htonl (ACL_PLUGIN_VERSION_MAJOR);
158  rmp->minor = htonl (ACL_PLUGIN_VERSION_MINOR);
159 
160  vl_api_send_msg (reg, (u8 *) rmp);
161 }
162 
163 static void
165  mp)
166 {
168  acl_main_t *am = &acl_main;
169  int rv = 0;
170 
171  /* *INDENT-OFF* */
172  REPLY_MACRO2 (VL_API_ACL_PLUGIN_CONTROL_PING_REPLY,
173  ({
174  rmp->vpe_pid = ntohl (getpid ());
175  }));
176  /* *INDENT-ON* */
177 }
178 
179 static void
181 {
182  clib_warning ("%v", out0);
183  vec_reset_length (out0);
184 }
185 
186 static void
188 {
189  vlib_cli_output (vm, "%v", out0);
190  vec_reset_length (out0);
191 }
192 
193 typedef void (*acl_vector_print_func_t) (vlib_main_t * vm, u8 * out0);
194 
195 static void
197  acl_main_t * am, int acl_index)
198 {
199  acl_rule_t *r;
200  acl_rule_t *acl_rules = am->acls[acl_index].rules;
201  u8 *out0 = format (0, "acl-index %u count %u tag {%s}\n", acl_index,
202  vec_len (acl_rules), am->acls[acl_index].tag);
203  int j;
204  vpr (vm, out0);
205  for (j = 0; j < vec_len (acl_rules); j++)
206  {
207  r = &acl_rules[j];
208  out0 = format (out0, " %9d: %s ", j, r->is_ipv6 ? "ipv6" : "ipv4");
209  out0 = format_acl_action (out0, r->is_permit);
210  out0 = format (out0, " src %U/%d", format_ip46_address, &r->src,
212  r->src_prefixlen);
213  out0 =
214  format (out0, " dst %U/%d", format_ip46_address, &r->dst,
215  r->is_ipv6 ? IP46_TYPE_IP6 : IP46_TYPE_IP4, r->dst_prefixlen);
216  out0 = format (out0, " proto %d", r->proto);
217  out0 = format (out0, " sport %d", r->src_port_or_type_first);
219  {
220  out0 = format (out0, "-%d", r->src_port_or_type_last);
221  }
222  out0 = format (out0, " dport %d", r->dst_port_or_code_first);
224  {
225  out0 = format (out0, "-%d", r->dst_port_or_code_last);
226  }
227  if (r->tcp_flags_mask || r->tcp_flags_value)
228  {
229  out0 =
230  format (out0, " tcpflags %d mask %d", r->tcp_flags_value,
231  r->tcp_flags_mask);
232  }
233  out0 = format (out0, "\n");
234  vpr (vm, out0);
235  }
236 }
237 
238 static void
241 {
242  acl_main_t *am = &acl_main;
244  int msg_size = sizeof (*rmp);
246 
248  if (rp == 0)
249  return;
250 
251  rmp = vl_msg_api_alloc (msg_size);
252  memset (rmp, 0, msg_size);
253  rmp->_vl_msg_id =
254  ntohs (VL_API_ACL_PLUGIN_GET_CONN_TABLE_MAX_ENTRIES_REPLY +
255  am->msg_id_base);
256  rmp->context = mp->context;
257  rmp->conn_table_max_entries = __bswap_64 (am->fa_conn_table_max_entries);
258 
259  vl_api_send_msg (rp, (u8 *) rmp);
260 }
261 
262 static void
264 {
265  acl_print_acl_x (print_cli_and_reset, vm, am, acl_index);
266 }
267 
268 static void
270 {
271  acl_print_acl_x (print_clib_warning_and_reset, vm, am, acl_index);
272 }
273 
274 static void
276 {
277 
278  u32 **ppolicy_epoch_by_swi =
279  is_input ? &am->input_policy_epoch_by_sw_if_index :
281  vec_validate (*ppolicy_epoch_by_swi, sw_if_index);
282 
283  u32 *p_epoch = vec_elt_at_index ((*ppolicy_epoch_by_swi), sw_if_index);
284  *p_epoch =
285  ((1 + *p_epoch) & FA_POLICY_EPOCH_MASK) +
286  (is_input * FA_POLICY_EPOCH_IS_INPUT);
287 }
288 
289 static void
290 try_increment_acl_policy_epoch (acl_main_t * am, u32 acl_num, int is_input)
291 {
292  u32 ***p_swi_vec_by_acl = is_input ? &am->input_sw_if_index_vec_by_acl
294  if (acl_num < vec_len (*p_swi_vec_by_acl))
295  {
296  u32 *p_swi;
297  vec_foreach (p_swi, (*p_swi_vec_by_acl)[acl_num])
298  {
299  increment_policy_epoch (am, *p_swi, is_input);
300  }
301 
302  }
303 }
304 
305 static void
307 {
308  try_increment_acl_policy_epoch (am, acl_num, 0);
309  try_increment_acl_policy_epoch (am, acl_num, 1);
310 }
311 
312 
313 static void
315 {
316  int i;
317  /* counters are set as vectors [acl#] pointing to vectors of [acl rule] */
319 
320  int old_len = vec_len (am->combined_acl_counters);
321 
322  vec_validate (am->combined_acl_counters, acl_index);
323 
324  for (i = old_len; i < vec_len (am->combined_acl_counters); i++)
325  {
326  am->combined_acl_counters[i].name = 0;
327  /* filled in once only */
329  format (0, "/acl/%d/matches%c", i, 0);
330  i32 rule_count = vec_len (am->acls[i].rules);
331  /* Validate one extra so we always have at least one counter for an ACL */
333  rule_count);
335  }
336 
337  /* (re)validate for the actual ACL that is getting added/updated */
338  i32 rule_count = vec_len (am->acls[acl_index].rules);
339  /* Validate one extra so we always have at least one counter for an ACL */
341  rule_count);
344 }
345 
346 static int
347 acl_api_invalid_prefix (const vl_api_prefix_t * prefix)
348 {
350  return ip_prefix_decode2 (prefix, &ip_prefix);
351 }
352 
353 static int
354 acl_add_list (u32 count, vl_api_acl_rule_t rules[],
355  u32 * acl_list_index, u8 * tag)
356 {
357  acl_main_t *am = &acl_main;
358  acl_list_t *a;
359  acl_rule_t *r;
360  acl_rule_t *acl_new_rules = 0;
361  int i;
362 
363  if (am->trace_acl > 255)
364  clib_warning ("API dbg: acl_add_list index %d tag %s", *acl_list_index,
365  tag);
366 
367  /* check if what they request is consistent */
368  for (i = 0; i < count; i++)
369  {
370  if (acl_api_invalid_prefix (&rules[i].src_prefix))
371  return VNET_API_ERROR_INVALID_SRC_ADDRESS;
372  if (acl_api_invalid_prefix (&rules[i].dst_prefix))
373  return VNET_API_ERROR_INVALID_DST_ADDRESS;
374  if (ntohs (rules[i].srcport_or_icmptype_first) >
375  ntohs (rules[i].srcport_or_icmptype_last))
376  return VNET_API_ERROR_INVALID_VALUE_2;
377  if (ntohs (rules[i].dstport_or_icmpcode_first) >
378  ntohs (rules[i].dstport_or_icmpcode_last))
379  return VNET_API_ERROR_INVALID_VALUE_2;
380  }
381 
382  if (*acl_list_index != ~0)
383  {
384  /* They supplied some number, let's see if this ACL exists */
385  if (pool_is_free_index (am->acls, *acl_list_index))
386  {
387  /* tried to replace a non-existent ACL, no point doing anything */
389  ("acl-plugin-error: Trying to replace nonexistent ACL %d (tag %s)",
390  *acl_list_index, tag);
391  return VNET_API_ERROR_NO_SUCH_ENTRY;
392  }
393  }
394  if (0 == count)
395  {
397  ("acl-plugin-warning: supplied no rules for ACL %d (tag %s)",
398  *acl_list_index, tag);
399  }
400 
401  void *oldheap = acl_set_heap (am);
402 
403  /* Create and populate the rules */
404  if (count > 0)
405  vec_validate (acl_new_rules, count - 1);
406 
407  for (i = 0; i < count; i++)
408  {
409  r = vec_elt_at_index (acl_new_rules, i);
410  clib_memset (r, 0, sizeof (*r));
411  r->is_permit = rules[i].is_permit;
412  r->is_ipv6 = rules[i].src_prefix.address.af;
413  ip_address_decode (&rules[i].src_prefix.address, &r->src);
414  ip_address_decode (&rules[i].dst_prefix.address, &r->dst);
415  r->src_prefixlen = rules[i].src_prefix.len;
416  r->dst_prefixlen = rules[i].dst_prefix.len;
417  r->proto = rules[i].proto;
422  r->tcp_flags_value = rules[i].tcp_flags_value;
423  r->tcp_flags_mask = rules[i].tcp_flags_mask;
424  }
425 
426  if (~0 == *acl_list_index)
427  {
428  /* Get ACL index */
430  clib_memset (a, 0, sizeof (*a));
431  /* Will return the newly allocated ACL index */
432  *acl_list_index = a - am->acls;
433  }
434  else
435  {
436  a = am->acls + *acl_list_index;
437  /* Get rid of the old rules */
438  if (a->rules)
439  vec_free (a->rules);
440  }
441  a->rules = acl_new_rules;
442  memcpy (a->tag, tag, sizeof (a->tag));
443  if (am->trace_acl > 255)
444  warning_acl_print_acl (am->vlib_main, am, *acl_list_index);
445  if (am->reclassify_sessions)
446  {
447  /* a change in an ACLs if they are applied may mean a new policy epoch */
448  policy_notify_acl_change (am, *acl_list_index);
449  }
450 
451  /* stats segment expects global heap, so restore it temporarily */
452  clib_mem_set_heap (oldheap);
453  validate_and_reset_acl_counters (am, *acl_list_index);
454  oldheap = acl_set_heap (am);
455 
456  /* notify the lookup contexts about the ACL changes */
458  clib_mem_set_heap (oldheap);
459  return 0;
460 }
461 
462 static int
463 acl_is_used_by (u32 acl_index, u32 ** foo_index_vec_by_acl)
464 {
465  if (acl_index < vec_len (foo_index_vec_by_acl))
466  {
467  if (vec_len (vec_elt (foo_index_vec_by_acl, acl_index)) > 0)
468  {
469  /* ACL is applied somewhere. */
470  return 1;
471  }
472  }
473  return 0;
474 }
475 
476 static int
477 acl_del_list (u32 acl_list_index)
478 {
479  acl_main_t *am = &acl_main;
480  acl_list_t *a;
481  if (pool_is_free_index (am->acls, acl_list_index))
482  {
483  return VNET_API_ERROR_NO_SUCH_ENTRY;
484  }
485  if (acl_is_used_by (acl_list_index, am->input_sw_if_index_vec_by_acl))
486  return VNET_API_ERROR_ACL_IN_USE_INBOUND;
487  if (acl_is_used_by (acl_list_index, am->output_sw_if_index_vec_by_acl))
488  return VNET_API_ERROR_ACL_IN_USE_OUTBOUND;
489  /* lookup contexts cover other cases, not just inbound/outbound, so check that */
490  if (acl_is_used_by (acl_list_index, am->lc_index_vec_by_acl))
491  return VNET_API_ERROR_ACL_IN_USE_BY_LOOKUP_CONTEXT;
492 
493  void *oldheap = acl_set_heap (am);
494 
495  /* now we can delete the ACL itself */
496  a = pool_elt_at_index (am->acls, acl_list_index);
497  if (a->rules)
498  vec_free (a->rules);
499  pool_put (am->acls, a);
500  /* acl_list_index is now free, notify the lookup contexts */
502  clib_mem_set_heap (oldheap);
503  return 0;
504 }
505 
506 static int
508 {
509  u64 *p64 = (u64 *) p;
510  /* Be tolerant to null pointer */
511  if (0 == p)
512  return 0;
513 
514  while ((0ULL == *p64) && ((u8 *) p64 - p) < size)
515  {
516  p64++;
517  }
518  return (p64 - (u64 *) p) / 2;
519 }
520 
521 static int
523  u32 mask_len, u32 next_table_index,
524  u32 miss_next_index, u32 * table_index,
525  int is_add)
526 {
527  u32 nbuckets = 32;
528  u32 memory_size = 2 << 22;
529  u32 skip = count_skip (mask, mask_len);
530  u32 match = (mask_len / 16) - skip;
531  u8 *skip_mask_ptr = mask + 16 * skip;
532  u32 current_data_flag = 0;
533  int current_data_offset = 0;
534 
535  if (0 == match)
536  match = 1;
537 
538  void *oldheap = clib_mem_set_heap (cm->vlib_main->heap_base);
539  int ret = vnet_classify_add_del_table (cm, skip_mask_ptr, nbuckets,
540  memory_size, skip, match,
541  next_table_index, miss_next_index,
542  table_index, current_data_flag,
543  current_data_offset, is_add,
544  1 /* delete_chain */ );
545  clib_mem_set_heap (oldheap);
546  return ret;
547 }
548 
549 static int
551 {
552  u16 **v = is_input
555  u16 *whitelist = (vec_len (v) > sw_if_index) ? vec_elt (v, sw_if_index) : 0;
556  return vec_len (whitelist) > 0;
557 }
558 
559 static void
561 {
562  void *oldheap = clib_mem_set_heap (am->vlib_main->heap_base);
565  sw_if_index);
566  clib_mem_set_heap (oldheap);
567 }
568 
569 
570 static int
572  int enable_disable)
573 {
574  int rv = 0;
575 
576  /* Utterly wrong? */
578  sw_if_index))
579  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
580 
581  if (clib_bitmap_get (am->in_acl_on_sw_if_index, sw_if_index) ==
582  enable_disable)
583  return 0;
584 
585  acl_fa_enable_disable (sw_if_index, 1, enable_disable);
586 
587  void *oldheap = clib_mem_set_heap (am->vlib_main->heap_base);
588  rv = vnet_l2_feature_enable_disable ("l2-input-ip4", "acl-plugin-in-ip4-l2",
589  sw_if_index, enable_disable, 0, 0);
590  if (rv)
591  clib_error ("Could not enable on input");
592  rv = vnet_l2_feature_enable_disable ("l2-input-ip6", "acl-plugin-in-ip6-l2",
593  sw_if_index, enable_disable, 0, 0);
594  if (rv)
595  clib_error ("Could not enable on input");
596 
597  if (intf_has_etype_whitelist (am, sw_if_index, 1))
598  vnet_l2_feature_enable_disable ("l2-input-nonip",
599  "acl-plugin-in-nonip-l2", sw_if_index,
600  enable_disable, 0, 0);
601 
602  clib_mem_set_heap (oldheap);
603 
605  clib_bitmap_set (am->in_acl_on_sw_if_index, sw_if_index, enable_disable);
606 
607  return rv;
608 }
609 
610 static int
612  int enable_disable)
613 {
614  int rv = 0;
615 
616  /* Utterly wrong? */
618  sw_if_index))
619  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
620 
621  if (clib_bitmap_get (am->out_acl_on_sw_if_index, sw_if_index) ==
622  enable_disable)
623  return 0;
624 
625  acl_fa_enable_disable (sw_if_index, 0, enable_disable);
626 
627  void *oldheap = clib_mem_set_heap (am->vlib_main->heap_base);
628  rv =
629  vnet_l2_feature_enable_disable ("l2-output-ip4", "acl-plugin-out-ip4-l2",
630  sw_if_index, enable_disable, 0, 0);
631  if (rv)
632  clib_error ("Could not enable on output");
633  rv =
634  vnet_l2_feature_enable_disable ("l2-output-ip6", "acl-plugin-out-ip6-l2",
635  sw_if_index, enable_disable, 0, 0);
636  if (rv)
637  clib_error ("Could not enable on output");
638  if (intf_has_etype_whitelist (am, sw_if_index, 0))
639  vnet_l2_feature_enable_disable ("l2-output-nonip",
640  "acl-plugin-out-nonip-l2", sw_if_index,
641  enable_disable, 0, 0);
642 
643 
644  clib_mem_set_heap (oldheap);
645 
647  clib_bitmap_set (am->out_acl_on_sw_if_index, sw_if_index, enable_disable);
648 
649  return rv;
650 }
651 
652 static int
654 {
655  int rv = 0;
656 
657  am->interface_acl_counters_enabled = enable_disable;
658 
659  return rv;
660 }
661 
662 static int
664  int is_input, int enable_disable)
665 {
666  if (is_input)
667  return acl_interface_in_enable_disable (am, sw_if_index, enable_disable);
668  else
669  return acl_interface_out_enable_disable (am, sw_if_index, enable_disable);
670 }
671 
672 static int
673 acl_is_not_defined (acl_main_t * am, u32 acl_list_index)
674 {
675  return (pool_is_free_index (am->acls, acl_list_index));
676 }
677 
678 static int
680  u8 is_input, u32 * vec_acl_list_index,
681  int *may_clear_sessions)
682 {
683  u32 *pacln;
684  uword *seen_acl_bitmap = 0;
685  uword *old_seen_acl_bitmap = 0;
686  uword *change_acl_bitmap = 0;
687  int acln;
688  int rv = 0;
689 
690 
691  if (am->trace_acl > 255)
693  ("API dbg: acl_interface_set_inout_acl_list: sw_if_index %d is_input %d acl_vec: [%U]",
694  sw_if_index, is_input, format_vec32, vec_acl_list_index, "%d");
695 
696  vec_foreach (pacln, vec_acl_list_index)
697  {
698  if (acl_is_not_defined (am, *pacln))
699  {
700  /* ACL is not defined. Can not apply */
701  clib_warning ("ERROR: ACL %d not defined", *pacln);
702  rv = VNET_API_ERROR_NO_SUCH_ENTRY;
703  goto done;
704  }
705  if (clib_bitmap_get (seen_acl_bitmap, *pacln))
706  {
707  /* ACL being applied twice within the list. error. */
708  clib_warning ("ERROR: ACL %d being applied twice", *pacln);
709  rv = VNET_API_ERROR_ENTRY_ALREADY_EXISTS;
710  goto done;
711  }
712  seen_acl_bitmap = clib_bitmap_set (seen_acl_bitmap, *pacln, 1);
713  }
714 
715 
716  u32 **pinout_lc_index_by_sw_if_index =
717  is_input ? &am->
718  input_lc_index_by_sw_if_index : &am->output_lc_index_by_sw_if_index;
719 
720  u32 ***pinout_acl_vec_by_sw_if_index =
721  is_input ? &am->
722  input_acl_vec_by_sw_if_index : &am->output_acl_vec_by_sw_if_index;
723 
724  u32 ***pinout_sw_if_index_vec_by_acl =
725  is_input ? &am->
726  input_sw_if_index_vec_by_acl : &am->output_sw_if_index_vec_by_acl;
727 
728  vec_validate ((*pinout_acl_vec_by_sw_if_index), sw_if_index);
729 
730  clib_bitmap_validate (old_seen_acl_bitmap, 1);
731 
732  vec_foreach (pacln, (*pinout_acl_vec_by_sw_if_index)[sw_if_index])
733  {
734  old_seen_acl_bitmap = clib_bitmap_set (old_seen_acl_bitmap, *pacln, 1);
735  }
736  change_acl_bitmap =
737  clib_bitmap_dup_xor (old_seen_acl_bitmap, seen_acl_bitmap);
738 
739  if (am->trace_acl > 255)
740  clib_warning ("bitmaps: old seen %U new seen %U changed %U",
741  format_bitmap_hex, old_seen_acl_bitmap, format_bitmap_hex,
742  seen_acl_bitmap, format_bitmap_hex, change_acl_bitmap);
743 
744 /* *INDENT-OFF* */
745  clib_bitmap_foreach(acln, change_acl_bitmap, ({
746  if (clib_bitmap_get(old_seen_acl_bitmap, acln)) {
747  /* ACL is being removed. */
748  if (acln < vec_len((*pinout_sw_if_index_vec_by_acl))) {
749  int index = vec_search((*pinout_sw_if_index_vec_by_acl)[acln], sw_if_index);
750  vec_del1((*pinout_sw_if_index_vec_by_acl)[acln], index);
751  }
752  } else {
753  /* ACL is being added. */
754  vec_validate((*pinout_sw_if_index_vec_by_acl), acln);
755  vec_add1((*pinout_sw_if_index_vec_by_acl)[acln], sw_if_index);
756  }
757  }));
758 /* *INDENT-ON* */
759 
760  vec_free ((*pinout_acl_vec_by_sw_if_index)[sw_if_index]);
761  (*pinout_acl_vec_by_sw_if_index)[sw_if_index] =
762  vec_dup (vec_acl_list_index);
763 
764  if (am->reclassify_sessions)
765  {
766  /* re-applying ACLs means a new policy epoch */
767  increment_policy_epoch (am, sw_if_index, is_input);
768  }
769  else
770  {
771  /* if no commonalities between the ACL# - then we should definitely clear the sessions */
772  if (may_clear_sessions && *may_clear_sessions
773  && !clib_bitmap_is_zero (change_acl_bitmap))
774  {
775  acl_clear_sessions (am, sw_if_index);
776  *may_clear_sessions = 0;
777  }
778  }
779 
780  /*
781  * prepare or delete the lookup context if necessary, and if context exists, set ACL list
782  */
783  vec_validate_init_empty ((*pinout_lc_index_by_sw_if_index), sw_if_index,
784  ~0);
785  /* lookup context creation is to be done in global heap */
786  void *oldheap = clib_mem_set_heap (am->vlib_main->heap_base);
787  if (vec_len (vec_acl_list_index) > 0)
788  {
789  u32 lc_index = (*pinout_lc_index_by_sw_if_index)[sw_if_index];
790  if (~0 == lc_index)
791  {
792  lc_index =
793  acl_plugin.get_lookup_context_index (am->interface_acl_user_id,
794  sw_if_index, is_input);
795  (*pinout_lc_index_by_sw_if_index)[sw_if_index] = lc_index;
796  }
797  acl_plugin.set_acl_vec_for_context (lc_index, vec_acl_list_index);
798  }
799  else
800  {
801  if (~0 != (*pinout_lc_index_by_sw_if_index)[sw_if_index])
802  {
803  acl_plugin.put_lookup_context_index ((*pinout_lc_index_by_sw_if_index)[sw_if_index]);
804  (*pinout_lc_index_by_sw_if_index)[sw_if_index] = ~0;
805  }
806  }
807  clib_mem_set_heap (oldheap);
808 
809  /* ensure ACL processing is enabled/disabled as needed */
810  acl_interface_inout_enable_disable (am, sw_if_index, is_input,
811  vec_len (vec_acl_list_index) > 0);
812 
813 done:
814  clib_bitmap_free (change_acl_bitmap);
815  clib_bitmap_free (seen_acl_bitmap);
816  clib_bitmap_free (old_seen_acl_bitmap);
817  return rv;
818 }
819 
820 static void
822  int *may_clear_sessions)
823 {
824  acl_main_t *am = &acl_main;
825  void *oldheap = acl_set_heap (am);
826  acl_interface_set_inout_acl_list (am, sw_if_index, is_input, 0,
827  may_clear_sessions);
828  clib_mem_set_heap (oldheap);
829 }
830 
831 static int
833  u32 acl_list_index)
834 {
835 
836  acl_main_t *am = &acl_main;
837  u32 *acl_vec = 0;
838  int may_clear_sessions = 1;
839 
840  int error_already_applied = is_input ? VNET_API_ERROR_ACL_IN_USE_INBOUND
841  : VNET_API_ERROR_ACL_IN_USE_OUTBOUND;
842 
843  u32 ***pinout_acl_vec_by_sw_if_index =
844  is_input ? &am->
845  input_acl_vec_by_sw_if_index : &am->output_acl_vec_by_sw_if_index;
846  int rv = 0;
847  void *oldheap = acl_set_heap (am);
848 
849  if (is_add)
850  {
851  vec_validate ((*pinout_acl_vec_by_sw_if_index), sw_if_index);
852  u32 index = vec_search ((*pinout_acl_vec_by_sw_if_index)[sw_if_index],
853  acl_list_index);
854 
855  if (~0 != index)
856  {
857  rv = error_already_applied;
858  goto done;
859  }
860 
861  acl_vec = vec_dup ((*pinout_acl_vec_by_sw_if_index)[sw_if_index]);
862  vec_add1 (acl_vec, acl_list_index);
863  }
864  else
865  {
866  if (sw_if_index >= vec_len (*pinout_acl_vec_by_sw_if_index))
867  {
868  rv = VNET_API_ERROR_NO_SUCH_ENTRY;
869  goto done;
870  }
871 
872  u32 index = vec_search ((*pinout_acl_vec_by_sw_if_index)[sw_if_index],
873  acl_list_index);
874 
875  if (~0 == index)
876  {
877  rv = VNET_API_ERROR_NO_SUCH_ENTRY;
878  goto done;
879  }
880 
881  acl_vec = vec_dup ((*pinout_acl_vec_by_sw_if_index)[sw_if_index]);
882  vec_del1 (acl_vec, index);
883  }
884 
885  rv = acl_interface_set_inout_acl_list (am, sw_if_index, is_input, acl_vec,
886  &may_clear_sessions);
887 done:
888  vec_free (acl_vec);
889  clib_mem_set_heap (oldheap);
890  return rv;
891 }
892 
893 static int
895  u16 * vec_out)
896 {
899 
902 
905 
906  /*
907  * if there are already inbound/outbound ACLs applied, toggle the
908  * enable/disable - this will recreate the necessary tables.
909  */
910 
911  if (vec_len (am->input_acl_vec_by_sw_if_index) > sw_if_index)
912  {
913  if (vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]) > 0)
914  {
915  acl_interface_in_enable_disable (am, sw_if_index, 0);
916  acl_interface_in_enable_disable (am, sw_if_index, 1);
917  }
918  }
919  if (vec_len (am->output_acl_vec_by_sw_if_index) > sw_if_index)
920  {
921  if (vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]) > 0)
922  {
923  acl_interface_out_enable_disable (am, sw_if_index, 0);
924  acl_interface_out_enable_disable (am, sw_if_index, 1);
925  }
926  }
927  return 0;
928 }
929 
930 
931 typedef struct
932 {
935  u8 mac_mask[6];
944  /* egress tables */
952 
953 static u32
954 macip_find_match_type (macip_match_type_t * mv, u8 * mac_mask, u8 prefix_len,
955  u8 is_ipv6)
956 {
957  u32 i;
958  if (mv)
959  {
960  for (i = 0; i < vec_len (mv); i++)
961  {
962  if ((mv[i].prefix_len == prefix_len) && (mv[i].is_ipv6 == is_ipv6)
963  && (0 == memcmp (mv[i].mac_mask, mac_mask, 6)))
964  {
965  return i;
966  }
967  }
968  }
969  return ~0;
970 }
971 
972 
973 /* Get metric used to sort match types.
974  The more specific and the more often seen - the bigger the metric */
975 static int
977 {
978  unsigned int mac_bits_set = 0;
979  unsigned int mac_byte;
980  int i;
981  for (i = 0; i < 6; i++)
982  {
983  mac_byte = m->mac_mask[i];
984  for (; mac_byte; mac_byte >>= 1)
985  mac_bits_set += mac_byte & 1;
986  }
987  /*
988  * Attempt to place the more specific and the more used rules on top.
989  * There are obvious caveat corner cases to this, but they do not
990  * seem to be sensible in real world (e.g. specific IPv4 with wildcard MAC
991  * going with a wildcard IPv4 with a specific MAC).
992  */
993  return m->prefix_len + mac_bits_set + m->is_ipv6 + 10 * m->count;
994 }
995 
996 static int
998 {
999  /* Ascending sort based on the metric values */
1000  return match_type_metric (m1) - match_type_metric (m2);
1001 }
1002 
1003 /* Get the offset of L3 source within ethernet packet */
1004 static int
1006 {
1007  if (is6)
1008  return (sizeof (ethernet_header_t) +
1009  offsetof (ip6_header_t, src_address));
1010  else
1011  return (sizeof (ethernet_header_t) +
1012  offsetof (ip4_header_t, src_address));
1013 }
1014 
1015 static int
1017 {
1018  if (is6)
1019  return (sizeof (ethernet_header_t) +
1020  offsetof (ip6_header_t, dst_address));
1021  else
1022  return (sizeof (ethernet_header_t) +
1023  offsetof (ip4_header_t, dst_address));
1024 }
1025 
1026 /*
1027  * return if the is_permit value also requires to create the egress tables
1028  * For backwards compatibility, we keep the is_permit = 1 to only
1029  * create the ingress tables, and the new value of 3 will also
1030  * create the egress tables based on destination.
1031  */
1032 static int
1034 {
1035  return (is_permit == 3);
1036 }
1037 
1038 static int
1040 {
1041  macip_match_type_t *mvec = NULL;
1042  macip_match_type_t *mt;
1043  macip_acl_list_t *a = pool_elt_at_index (am->macip_acls, macip_acl_index);
1044  int i;
1045  u32 match_type_index;
1046  u32 last_table;
1047  u32 out_last_table;
1048  u8 mask[5 * 16];
1050 
1051  /* Count the number of different types of rules */
1052  for (i = 0; i < a->count; i++)
1053  {
1054  if (~0 ==
1055  (match_type_index =
1057  a->rules[i].src_prefixlen,
1058  a->rules[i].is_ipv6)))
1059  {
1060  match_type_index = vec_len (mvec);
1061  vec_validate (mvec, match_type_index);
1062  memcpy (mvec[match_type_index].mac_mask,
1063  a->rules[i].src_mac_mask, 6);
1064  mvec[match_type_index].prefix_len = a->rules[i].src_prefixlen;
1065  mvec[match_type_index].is_ipv6 = a->rules[i].is_ipv6;
1066  mvec[match_type_index].has_egress = 0;
1067  mvec[match_type_index].table_index = ~0;
1068  mvec[match_type_index].arp_table_index = ~0;
1069  mvec[match_type_index].dot1q_table_index = ~0;
1070  mvec[match_type_index].dot1ad_table_index = ~0;
1071  mvec[match_type_index].arp_dot1q_table_index = ~0;
1072  mvec[match_type_index].arp_dot1ad_table_index = ~0;
1073  mvec[match_type_index].out_table_index = ~0;
1074  mvec[match_type_index].out_arp_table_index = ~0;
1075  mvec[match_type_index].out_dot1q_table_index = ~0;
1076  mvec[match_type_index].out_dot1ad_table_index = ~0;
1077  mvec[match_type_index].out_arp_dot1q_table_index = ~0;
1078  mvec[match_type_index].out_arp_dot1ad_table_index = ~0;
1079  }
1080  mvec[match_type_index].count++;
1081  mvec[match_type_index].has_egress |=
1083  }
1084  /* Put the most frequently used tables last in the list so we can create classifier tables in reverse order */
1086  /* Create the classifier tables */
1087  last_table = ~0;
1088  out_last_table = ~0;
1089  /* First add ARP tables */
1090  vec_foreach (mt, mvec)
1091  {
1092  int mask_len;
1093  int is6 = mt->is_ipv6;
1094  int tags;
1095  u32 *last_tag_table;
1096  u32 *out_last_tag_table;
1097  u32 l3_offset;
1098 
1099  if (!is6)
1100  {
1101  /*
1102  0 1 2 3
1103  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1104  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1105  | Destination Address |
1106  + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1107  | | |
1108  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
1109  | Source Address |
1110  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1111  | EtherType | Hardware Type |
1112  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1113  | Protocol Type | Hw addr len | Proto addr len|
1114  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1115  | Opcode | |
1116  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
1117  | Sender Hardware Address |
1118  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1119  | Sender Protocol Address |
1120  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1121  | Target Hardware Address |
1122  + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1123  | | TargetProtocolAddress |
1124  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1125  | |
1126  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1127  */
1128  for (tags = 2; tags >= 0; tags--)
1129  {
1130  clib_memset (mask, 0, sizeof (mask));
1131  /* source MAC address */
1132  memcpy (&mask[6], mt->mac_mask, 6);
1133 
1134  switch (tags)
1135  {
1136  case 0:
1137  default:
1138  clib_memset (&mask[12], 0xff, 2); /* ethernet protocol */
1139  l3_offset = 14;
1140  last_tag_table = &mt->arp_table_index;
1141  break;
1142  case 1:
1143  clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */
1144  clib_memset (&mask[16], 0xff, 2); /* ethernet protocol */
1145  l3_offset = 18;
1146  last_tag_table = &mt->arp_dot1q_table_index;
1147  break;
1148  case 2:
1149  clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */
1150  clib_memset (&mask[16], 0xff, 2); /* VLAN tag2 */
1151  clib_memset (&mask[20], 0xff, 2); /* ethernet protocol */
1152  l3_offset = 22;
1153  last_tag_table = &mt->arp_dot1ad_table_index;
1154  break;
1155  }
1156 
1157  /* sender hardware address within ARP */
1158  memcpy (&mask[l3_offset + 8], mt->mac_mask, 6);
1159  /* sender protocol address within ARP */
1160  for (i = 0; i < (mt->prefix_len / 8); i++)
1161  mask[l3_offset + 14 + i] = 0xff;
1162  if (mt->prefix_len % 8)
1163  mask[l3_offset + 14 + (mt->prefix_len / 8)] =
1164  0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
1165 
1166  mask_len = ((l3_offset + 14 + ((mt->prefix_len + 7) / 8) +
1167  (sizeof (u32x4) -
1168  1)) / sizeof (u32x4)) * sizeof (u32x4);
1169  acl_classify_add_del_table_small (cm, mask, mask_len, last_table,
1170  (~0 == last_table) ? 0 : ~0,
1171  last_tag_table, 1);
1172  last_table = *last_tag_table;
1173  if (mt->has_egress)
1174  {
1175  /* egress ARP table */
1176  clib_memset (mask, 0, sizeof (mask));
1177 
1178  switch (tags)
1179  {
1180  case 0:
1181  default:
1182  clib_memset (&mask[12], 0xff, 2); /* ethernet protocol */
1183  l3_offset = 14;
1184  out_last_tag_table = &mt->out_arp_table_index;
1185  break;
1186  case 1:
1187  clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */
1188  clib_memset (&mask[16], 0xff, 2); /* ethernet protocol */
1189  l3_offset = 18;
1190  out_last_tag_table = &mt->out_arp_dot1q_table_index;
1191  break;
1192  case 2:
1193  clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */
1194  clib_memset (&mask[16], 0xff, 2); /* VLAN tag2 */
1195  clib_memset (&mask[20], 0xff, 2); /* ethernet protocol */
1196  l3_offset = 22;
1197  out_last_tag_table = &mt->out_arp_dot1ad_table_index;
1198  break;
1199  }
1200 
1201  /* AYXX: FIXME here - can we tighten the ARP-related table more ? */
1202  /* mask captures just the destination and the ethertype */
1203  mask_len = ((l3_offset +
1204  (sizeof (u32x4) -
1205  1)) / sizeof (u32x4)) * sizeof (u32x4);
1206  acl_classify_add_del_table_small (cm, mask, mask_len,
1207  out_last_table,
1208  (~0 ==
1209  out_last_table) ? 0 : ~0,
1210  out_last_tag_table, 1);
1211  out_last_table = *out_last_tag_table;
1212  }
1213  }
1214  }
1215  }
1216  /* Now add IP[46] tables */
1217  vec_foreach (mt, mvec)
1218  {
1219  int mask_len;
1220  int is6 = mt->is_ipv6;
1221  int l3_src_offs;
1222  int l3_dst_offs;
1223  int tags;
1224  u32 *last_tag_table;
1225  u32 *out_last_tag_table;
1226 
1227  /*
1228  * create chained tables for VLAN (no-tags, dot1q and dot1ad) packets
1229  */
1230  for (tags = 2; tags >= 0; tags--)
1231  {
1232  clib_memset (mask, 0, sizeof (mask));
1233  memcpy (&mask[6], mt->mac_mask, 6);
1234  l3_src_offs = tags * 4 + get_l3_src_offset (is6);
1235  switch (tags)
1236  {
1237  case 0:
1238  default:
1239  clib_memset (&mask[12], 0xff, 2); /* ethernet protocol */
1240  last_tag_table = &mt->table_index;
1241  break;
1242  case 1:
1243  clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */
1244  clib_memset (&mask[16], 0xff, 2); /* ethernet protocol */
1245  last_tag_table = &mt->dot1q_table_index;
1246  break;
1247  case 2:
1248  clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */
1249  clib_memset (&mask[16], 0xff, 2); /* VLAN tag2 */
1250  clib_memset (&mask[20], 0xff, 2); /* ethernet protocol */
1251  last_tag_table = &mt->dot1ad_table_index;
1252  break;
1253  }
1254  for (i = 0; i < (mt->prefix_len / 8); i++)
1255  {
1256  mask[l3_src_offs + i] = 0xff;
1257  }
1258  if (mt->prefix_len % 8)
1259  {
1260  mask[l3_src_offs + (mt->prefix_len / 8)] =
1261  0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
1262  }
1263  /*
1264  * Round-up the number of bytes needed to store the prefix,
1265  * and round up the number of vectors too
1266  */
1267  mask_len = ((l3_src_offs + ((mt->prefix_len + 7) / 8) +
1268  (sizeof (u32x4) - 1)) / sizeof (u32x4)) * sizeof (u32x4);
1269  acl_classify_add_del_table_small (cm, mask, mask_len, last_table,
1270  (~0 == last_table) ? 0 : ~0,
1271  last_tag_table, 1);
1272  last_table = *last_tag_table;
1273  }
1274  if (mt->has_egress)
1275  {
1276  for (tags = 2; tags >= 0; tags--)
1277  {
1278  clib_memset (mask, 0, sizeof (mask));
1279  /* MAC destination */
1280  memcpy (&mask[0], mt->mac_mask, 6);
1281  l3_dst_offs = tags * 4 + get_l3_dst_offset (is6);
1282  switch (tags)
1283  {
1284  case 0:
1285  default:
1286  clib_memset (&mask[12], 0xff, 2); /* ethernet protocol */
1287  out_last_tag_table = &mt->out_table_index;
1288  break;
1289  case 1:
1290  clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */
1291  clib_memset (&mask[16], 0xff, 2); /* ethernet protocol */
1292  out_last_tag_table = &mt->out_dot1q_table_index;
1293  break;
1294  case 2:
1295  clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */
1296  clib_memset (&mask[16], 0xff, 2); /* VLAN tag2 */
1297  clib_memset (&mask[20], 0xff, 2); /* ethernet protocol */
1298  out_last_tag_table = &mt->out_dot1ad_table_index;
1299  break;
1300  }
1301  for (i = 0; i < (mt->prefix_len / 8); i++)
1302  {
1303  mask[l3_dst_offs + i] = 0xff;
1304  }
1305  if (mt->prefix_len % 8)
1306  {
1307  mask[l3_dst_offs + (mt->prefix_len / 8)] =
1308  0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
1309  }
1310  /*
1311  * Round-up the number of bytes needed to store the prefix,
1312  * and round up the number of vectors too
1313  */
1314  mask_len = ((l3_dst_offs + ((mt->prefix_len + 7) / 8) +
1315  (sizeof (u32x4) -
1316  1)) / sizeof (u32x4)) * sizeof (u32x4);
1317  acl_classify_add_del_table_small (cm, mask, mask_len,
1318  out_last_table,
1319  (~0 == out_last_table) ? 0 : ~0,
1320  out_last_tag_table, 1);
1321  out_last_table = *out_last_tag_table;
1322  }
1323  }
1324  }
1325  a->ip4_table_index = last_table;
1326  a->ip6_table_index = last_table;
1327  a->l2_table_index = last_table;
1328 
1329  a->out_ip4_table_index = out_last_table;
1330  a->out_ip6_table_index = out_last_table;
1331  a->out_l2_table_index = out_last_table;
1332 
1333  /* Populate the classifier tables with rules from the MACIP ACL */
1334  for (i = 0; i < a->count; i++)
1335  {
1336  u32 action = 0;
1337  u32 metadata = 0;
1338  int is6 = a->rules[i].is_ipv6;
1339  int l3_src_offs;
1340  int l3_dst_offs;
1341  u32 tag_table;
1342  int tags, eth;
1343 
1344  match_type_index =
1346  a->rules[i].src_prefixlen,
1347  a->rules[i].is_ipv6);
1348  ASSERT (match_type_index != ~0);
1349 
1350  for (tags = 2; tags >= 0; tags--)
1351  {
1352  clib_memset (mask, 0, sizeof (mask));
1353  l3_src_offs = tags * 4 + get_l3_src_offset (is6);
1354  memcpy (&mask[6], a->rules[i].src_mac, 6);
1355  switch (tags)
1356  {
1357  case 0:
1358  default:
1359  tag_table = mvec[match_type_index].table_index;
1360  eth = 12;
1361  break;
1362  case 1:
1363  tag_table = mvec[match_type_index].dot1q_table_index;
1364  mask[12] = 0x81;
1365  mask[13] = 0x00;
1366  eth = 16;
1367  break;
1368  case 2:
1369  tag_table = mvec[match_type_index].dot1ad_table_index;
1370  mask[12] = 0x88;
1371  mask[13] = 0xa8;
1372  mask[16] = 0x81;
1373  mask[17] = 0x00;
1374  eth = 20;
1375  break;
1376  }
1377  if (is6)
1378  {
1379  memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip6, 16);
1380  mask[eth] = 0x86;
1381  mask[eth + 1] = 0xdd;
1382  }
1383  else
1384  {
1385  memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip4, 4);
1386  mask[eth] = 0x08;
1387  mask[eth + 1] = 0x00;
1388  }
1389 
1390  /* add session to table mvec[match_type_index].table_index; */
1391  vnet_classify_add_del_session (cm, tag_table,
1392  mask, a->rules[i].is_permit ? ~0 : 0,
1393  i, 0, action, metadata, 1);
1394  clib_memset (&mask[12], 0, sizeof (mask) - 12);
1395  }
1396 
1397  /* add ARP table entry too */
1398  if (!is6 && (mvec[match_type_index].arp_table_index != ~0))
1399  {
1400  clib_memset (mask, 0, sizeof (mask));
1401  memcpy (&mask[6], a->rules[i].src_mac, 6);
1402 
1403  for (tags = 2; tags >= 0; tags--)
1404  {
1405  switch (tags)
1406  {
1407  case 0:
1408  default:
1409  tag_table = mvec[match_type_index].arp_table_index;
1410  mask[12] = 0x08;
1411  mask[13] = 0x06;
1412  l3_src_offs = 14;
1413  break;
1414  case 1:
1415  tag_table = mvec[match_type_index].arp_dot1q_table_index;
1416  mask[12] = 0x81;
1417  mask[13] = 0x00;
1418  mask[16] = 0x08;
1419  mask[17] = 0x06;
1420  l3_src_offs = 18;
1421  break;
1422  case 2:
1423  tag_table = mvec[match_type_index].arp_dot1ad_table_index;
1424  mask[12] = 0x88;
1425  mask[13] = 0xa8;
1426  mask[16] = 0x81;
1427  mask[17] = 0x00;
1428  mask[20] = 0x08;
1429  mask[21] = 0x06;
1430  l3_src_offs = 22;
1431  break;
1432  }
1433 
1434  memcpy (&mask[l3_src_offs + 8], a->rules[i].src_mac, 6);
1435  memcpy (&mask[l3_src_offs + 14], &a->rules[i].src_ip_addr.ip4,
1436  4);
1437  vnet_classify_add_del_session (cm, tag_table, mask,
1438  a->rules[i].is_permit ? ~0 : 0,
1439  i, 0, action, metadata, 1);
1440  }
1441  }
1443  {
1444  /* Add the egress entry with destination set */
1445  for (tags = 2; tags >= 0; tags--)
1446  {
1447  clib_memset (mask, 0, sizeof (mask));
1448  l3_dst_offs = tags * 4 + get_l3_dst_offset (is6);
1449  /* src mac in the other direction becomes dst */
1450  memcpy (&mask[0], a->rules[i].src_mac, 6);
1451  switch (tags)
1452  {
1453  case 0:
1454  default:
1455  tag_table = mvec[match_type_index].out_table_index;
1456  eth = 12;
1457  break;
1458  case 1:
1459  tag_table = mvec[match_type_index].out_dot1q_table_index;
1460  mask[12] = 0x81;
1461  mask[13] = 0x00;
1462  eth = 16;
1463  break;
1464  case 2:
1465  tag_table = mvec[match_type_index].out_dot1ad_table_index;
1466  mask[12] = 0x88;
1467  mask[13] = 0xa8;
1468  mask[16] = 0x81;
1469  mask[17] = 0x00;
1470  eth = 20;
1471  break;
1472  }
1473  if (is6)
1474  {
1475  memcpy (&mask[l3_dst_offs], &a->rules[i].src_ip_addr.ip6,
1476  16);
1477  mask[eth] = 0x86;
1478  mask[eth + 1] = 0xdd;
1479  }
1480  else
1481  {
1482  memcpy (&mask[l3_dst_offs], &a->rules[i].src_ip_addr.ip4,
1483  4);
1484  mask[eth] = 0x08;
1485  mask[eth + 1] = 0x00;
1486  }
1487 
1488  /* add session to table mvec[match_type_index].table_index; */
1489  vnet_classify_add_del_session (cm, tag_table,
1490  mask,
1491  a->rules[i].is_permit ? ~0 : 0,
1492  i, 0, action, metadata, 1);
1493  // clib_memset (&mask[12], 0, sizeof (mask) - 12);
1494  }
1495 
1496  /* add ARP table entry too */
1497  if (!is6 && (mvec[match_type_index].out_arp_table_index != ~0))
1498  {
1499  for (tags = 2; tags >= 0; tags--)
1500  {
1501  clib_memset (mask, 0, sizeof (mask));
1502  switch (tags)
1503  {
1504  case 0:
1505  default:
1506  tag_table = mvec[match_type_index].out_arp_table_index;
1507  mask[12] = 0x08;
1508  mask[13] = 0x06;
1509  break;
1510  case 1:
1511  tag_table =
1512  mvec[match_type_index].out_arp_dot1q_table_index;
1513  mask[12] = 0x81;
1514  mask[13] = 0x00;
1515  mask[16] = 0x08;
1516  mask[17] = 0x06;
1517  break;
1518  case 2:
1519  tag_table =
1520  mvec[match_type_index].out_arp_dot1ad_table_index;
1521  mask[12] = 0x88;
1522  mask[13] = 0xa8;
1523  mask[16] = 0x81;
1524  mask[17] = 0x00;
1525  mask[20] = 0x08;
1526  mask[21] = 0x06;
1527  break;
1528  }
1529 
1530  vnet_classify_add_del_session (cm, tag_table,
1531  mask,
1532  a->
1533  rules[i].is_permit ? ~0 : 0,
1534  i, 0, action, metadata, 1);
1535  }
1536  }
1537  }
1538  }
1539  return 0;
1540 }
1541 
1542 static void
1544 {
1546  macip_acl_list_t *a = pool_elt_at_index (am->macip_acls, macip_acl_index);
1547 
1548  if (a->ip4_table_index != ~0)
1549  {
1550  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0,
1551  &a->ip4_table_index, 0);
1552  a->ip4_table_index = ~0;
1553  }
1554  if (a->ip6_table_index != ~0)
1555  {
1556  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0,
1557  &a->ip6_table_index, 0);
1558  a->ip6_table_index = ~0;
1559  }
1560  if (a->l2_table_index != ~0)
1561  {
1562  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0, &a->l2_table_index,
1563  0);
1564  a->l2_table_index = ~0;
1565  }
1566  if (a->out_ip4_table_index != ~0)
1567  {
1568  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0,
1569  &a->out_ip4_table_index, 0);
1570  a->out_ip4_table_index = ~0;
1571  }
1572  if (a->out_ip6_table_index != ~0)
1573  {
1574  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0,
1575  &a->out_ip6_table_index, 0);
1576  a->out_ip6_table_index = ~0;
1577  }
1578  if (a->out_l2_table_index != ~0)
1579  {
1580  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0,
1581  &a->out_l2_table_index, 0);
1582  a->out_l2_table_index = ~0;
1583  }
1584 }
1585 
1586 static int
1588  int is_apply)
1589 {
1590  int rv = 0;
1591  int rv0 = 0;
1592  int i;
1593  macip_acl_list_t *a = pool_elt_at_index (am->macip_acls, acl_index);
1594 
1595  for (i = 0; i < vec_len (am->macip_acl_by_sw_if_index); i++)
1596  if (vec_elt (am->macip_acl_by_sw_if_index, i) == acl_index)
1597  {
1600  is_apply);
1601  /* return the first unhappy outcome but make try to plough through. */
1602  rv = rv || rv0;
1603  rv0 =
1606  a->out_l2_table_index, is_apply);
1607  /* return the first unhappy outcome but make try to plough through. */
1608  rv = rv || rv0;
1609  }
1610  return rv;
1611 }
1612 
1613 static int
1614 macip_acl_add_list (u32 count, vl_api_macip_acl_rule_t rules[],
1615  u32 * acl_list_index, u8 * tag)
1616 {
1617  acl_main_t *am = &acl_main;
1619  macip_acl_rule_t *r;
1620  macip_acl_rule_t *acl_new_rules = 0;
1621  int i;
1622  int rv = 0;
1623 
1624  if (*acl_list_index != ~0)
1625  {
1626  /* They supplied some number, let's see if this MACIP ACL exists */
1627  if (pool_is_free_index (am->macip_acls, *acl_list_index))
1628  {
1629  /* tried to replace a non-existent ACL, no point doing anything */
1630  clib_warning
1631  ("acl-plugin-error: Trying to replace nonexistent MACIP ACL %d (tag %s)",
1632  *acl_list_index, tag);
1633  return VNET_API_ERROR_NO_SUCH_ENTRY;
1634  }
1635  }
1636 
1637  if (0 == count)
1638  {
1639  clib_warning
1640  ("acl-plugin-warning: Trying to create empty MACIP ACL (tag %s)",
1641  tag);
1642  }
1643  /* if replacing the ACL, unapply the classifier tables first - they will be gone.. */
1644  if (~0 != *acl_list_index)
1645  rv = macip_maybe_apply_unapply_classifier_tables (am, *acl_list_index, 0);
1646  void *oldheap = acl_set_heap (am);
1647  /* Create and populate the rules */
1648  if (count > 0)
1649  vec_validate (acl_new_rules, count - 1);
1650 
1651  for (i = 0; i < count; i++)
1652  {
1653  r = &acl_new_rules[i];
1654  r->is_permit = rules[i].is_permit;
1655  r->is_ipv6 = rules[i].src_prefix.address.af;
1656  mac_address_decode (rules[i].src_mac, (mac_address_t *) & r->src_mac);
1657  mac_address_decode (rules[i].src_mac_mask,
1658  (mac_address_t *) & r->src_mac_mask);
1659  ip_address_decode (&rules[i].src_prefix.address, &r->src_ip_addr);
1660  r->src_prefixlen = rules[i].src_prefix.len;
1661  }
1662 
1663  if (~0 == *acl_list_index)
1664  {
1665  /* Get ACL index */
1667  clib_memset (a, 0, sizeof (*a));
1668  /* Will return the newly allocated ACL index */
1669  *acl_list_index = a - am->macip_acls;
1670  }
1671  else
1672  {
1673  a = pool_elt_at_index (am->macip_acls, *acl_list_index);
1674  if (a->rules)
1675  {
1676  vec_free (a->rules);
1677  }
1678  macip_destroy_classify_tables (am, *acl_list_index);
1679  }
1680 
1681  a->rules = acl_new_rules;
1682  a->count = count;
1683  memcpy (a->tag, tag, sizeof (a->tag));
1684 
1685  /* Create and populate the classifier tables */
1686  macip_create_classify_tables (am, *acl_list_index);
1687  clib_mem_set_heap (oldheap);
1688  /* If the ACL was already applied somewhere, reapply the newly created tables */
1689  rv = rv
1690  || macip_maybe_apply_unapply_classifier_tables (am, *acl_list_index, 1);
1691  return rv;
1692 }
1693 
1694 /* No check that sw_if_index denotes a valid interface - the callers
1695  * were supposed to validate.
1696  *
1697  * That said, if sw_if_index corresponds to an interface that exists at all,
1698  * this function must return errors accordingly if the ACL is not applied.
1699  */
1700 
1701 static int
1703 {
1704  int rv;
1705  u32 macip_acl_index;
1707 
1708  /* The vector is too short - MACIP ACL is not applied */
1709  if (sw_if_index >= vec_len (am->macip_acl_by_sw_if_index))
1710  return VNET_API_ERROR_NO_SUCH_ENTRY;
1711 
1712  macip_acl_index = am->macip_acl_by_sw_if_index[sw_if_index];
1713  /* No point in deleting MACIP ACL which is not applied */
1714  if (~0 == macip_acl_index)
1715  return VNET_API_ERROR_NO_SUCH_ENTRY;
1716 
1717  a = pool_elt_at_index (am->macip_acls, macip_acl_index);
1718  /* remove the classifier tables off the interface L2 ACL */
1719  rv =
1720  vnet_set_input_acl_intfc (am->vlib_main, sw_if_index, a->ip4_table_index,
1721  a->ip6_table_index, a->l2_table_index, 0);
1722  rv |=
1723  vnet_set_output_acl_intfc (am->vlib_main, sw_if_index,
1725  a->out_l2_table_index, 0);
1726  /* Unset the MACIP ACL index */
1728  /* macip_acl_interface_add_acl did a vec_add1() to this previously, so [sw_if_index] should be valid */
1729  u32 index = vec_search (am->sw_if_index_vec_by_macip_acl[macip_acl_index],
1730  sw_if_index);
1731  if (index != ~0)
1732  vec_del1 (am->sw_if_index_vec_by_macip_acl[macip_acl_index], index);
1733  return rv;
1734 }
1735 
1736 /* No check for validity of sw_if_index - the callers were supposed to validate */
1737 
1738 static int
1740  u32 macip_acl_index)
1741 {
1743  int rv;
1744  if (pool_is_free_index (am->macip_acls, macip_acl_index))
1745  {
1746  return VNET_API_ERROR_NO_SUCH_ENTRY;
1747  }
1748  void *oldheap = acl_set_heap (am);
1749  a = pool_elt_at_index (am->macip_acls, macip_acl_index);
1750  vec_validate_init_empty (am->macip_acl_by_sw_if_index, sw_if_index, ~0);
1751  vec_validate (am->sw_if_index_vec_by_macip_acl, macip_acl_index);
1752  vec_add1 (am->sw_if_index_vec_by_macip_acl[macip_acl_index], sw_if_index);
1753  clib_mem_set_heap (oldheap);
1754  /* If there already a MACIP ACL applied, unapply it */
1755  if (~0 != am->macip_acl_by_sw_if_index[sw_if_index])
1756  macip_acl_interface_del_acl (am, sw_if_index);
1757  am->macip_acl_by_sw_if_index[sw_if_index] = macip_acl_index;
1758 
1759  /* Apply the classifier tables for L2 ACLs */
1760  rv =
1761  vnet_set_input_acl_intfc (am->vlib_main, sw_if_index, a->ip4_table_index,
1762  a->ip6_table_index, a->l2_table_index, 1);
1763  rv |=
1764  vnet_set_output_acl_intfc (am->vlib_main, sw_if_index,
1766  a->out_l2_table_index, 1);
1767  return rv;
1768 }
1769 
1770 static int
1771 macip_acl_del_list (u32 acl_list_index)
1772 {
1773  acl_main_t *am = &acl_main;
1775  int i;
1776  if (pool_is_free_index (am->macip_acls, acl_list_index))
1777  {
1778  return VNET_API_ERROR_NO_SUCH_ENTRY;
1779  }
1780 
1781  /* delete any references to the ACL */
1782  for (i = 0; i < vec_len (am->macip_acl_by_sw_if_index); i++)
1783  {
1784  if (am->macip_acl_by_sw_if_index[i] == acl_list_index)
1785  {
1787  }
1788  }
1789 
1790  void *oldheap = acl_set_heap (am);
1791  /* Now that classifier tables are detached, clean them up */
1792  macip_destroy_classify_tables (am, acl_list_index);
1793 
1794  /* now we can delete the ACL itself */
1795  a = pool_elt_at_index (am->macip_acls, acl_list_index);
1796  if (a->rules)
1797  {
1798  vec_free (a->rules);
1799  }
1800  pool_put (am->macip_acls, a);
1801  clib_mem_set_heap (oldheap);
1802  return 0;
1803 }
1804 
1805 
1806 static int
1808  u32 acl_list_index)
1809 {
1810  acl_main_t *am = &acl_main;
1811  int rv = -1;
1812  if (is_add)
1813  {
1814  rv = macip_acl_interface_add_acl (am, sw_if_index, acl_list_index);
1815  }
1816  else
1817  {
1818  rv = macip_acl_interface_del_acl (am, sw_if_index);
1819  }
1820  return rv;
1821 }
1822 
1823 /*
1824  * If the client does not allocate enough memory for a variable-length
1825  * message, and then proceed to use it as if the full memory allocated,
1826  * absent the check we happily consume that on the VPP side, and go
1827  * along as if nothing happened. However, the resulting
1828  * effects range from just garbage in the API decode
1829  * (because the decoder snoops too far), to potential memory
1830  * corruptions.
1831  *
1832  * This verifies that the actual length of the message is
1833  * at least expected_len, and complains loudly if it is not.
1834  *
1835  * A failing check here is 100% a software bug on the API user side,
1836  * so we might as well yell.
1837  *
1838  */
1839 static int
1840 verify_message_len (void *mp, u32 expected_len, char *where)
1841 {
1842  u32 supplied_len = vl_msg_api_get_msg_length (mp);
1843  if (supplied_len < expected_len)
1844  {
1845  clib_warning ("%s: Supplied message length %d is less than expected %d",
1846  where, supplied_len, expected_len);
1847  return 0;
1848  }
1849  else
1850  {
1851  return 1;
1852  }
1853 }
1854 
1855 /* API message handler */
1856 static void
1858 {
1860  acl_main_t *am = &acl_main;
1861  int rv;
1862  u32 acl_list_index = ntohl (mp->acl_index);
1863  u32 acl_count = ntohl (mp->count);
1864  u32 expected_len = sizeof (*mp) + acl_count * sizeof (mp->r[0]);
1865 
1866  if (verify_message_len (mp, expected_len, "acl_add_replace"))
1867  {
1868  rv = acl_add_list (acl_count, mp->r, &acl_list_index, mp->tag);
1869  }
1870  else
1871  {
1872  rv = VNET_API_ERROR_INVALID_VALUE;
1873  }
1874 
1875  /* *INDENT-OFF* */
1876  REPLY_MACRO2(VL_API_ACL_ADD_REPLACE_REPLY,
1877  ({
1878  rmp->acl_index = htonl(acl_list_index);
1879  }));
1880  /* *INDENT-ON* */
1881 }
1882 
1883 static void
1885 {
1886  acl_main_t *am = &acl_main;
1887  vl_api_acl_del_reply_t *rmp;
1888  int rv;
1889 
1890  rv = acl_del_list (ntohl (mp->acl_index));
1891 
1892  REPLY_MACRO (VL_API_ACL_DEL_REPLY);
1893 }
1894 
1895 
1896 static void
1899 {
1900  acl_main_t *am = &acl_main;
1901  vl_api_acl_stats_intf_counters_enable_reply_t *rmp;
1902  int rv;
1903 
1905 
1906  REPLY_MACRO (VL_API_ACL_DEL_REPLY);
1907 }
1908 
1909 
1910 static void
1912 {
1913  acl_main_t *am = &acl_main;
1915  u32 sw_if_index = ntohl (mp->sw_if_index);
1916  vl_api_acl_interface_add_del_reply_t *rmp;
1917  int rv = -1;
1918 
1919  if (pool_is_free_index (im->sw_interfaces, sw_if_index))
1920  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1921  else
1922  rv =
1923  acl_interface_add_del_inout_acl (sw_if_index, mp->is_add,
1924  mp->is_input, ntohl (mp->acl_index));
1925 
1926  REPLY_MACRO (VL_API_ACL_INTERFACE_ADD_DEL_REPLY);
1927 }
1928 
1929 static void
1932 {
1933  acl_main_t *am = &acl_main;
1934  vl_api_acl_interface_set_acl_list_reply_t *rmp;
1935  int rv = 0;
1936  int i;
1938  u32 sw_if_index = ntohl (mp->sw_if_index);
1939 
1940  if (pool_is_free_index (im->sw_interfaces, sw_if_index))
1941  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1942  else
1943  {
1944  int may_clear_sessions = 1;
1945  for (i = 0; i < mp->count; i++)
1946  {
1947  if (acl_is_not_defined (am, ntohl (mp->acls[i])))
1948  {
1949  /* ACL does not exist, so we can not apply it */
1950  rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1951  }
1952  }
1953  if (0 == rv)
1954  {
1955  void *oldheap = acl_set_heap (am);
1956 
1957  u32 *in_acl_vec = 0;
1958  u32 *out_acl_vec = 0;
1959  for (i = 0; i < mp->count; i++)
1960  if (i < mp->n_input)
1961  vec_add1 (in_acl_vec, clib_net_to_host_u32 (mp->acls[i]));
1962  else
1963  vec_add1 (out_acl_vec, clib_net_to_host_u32 (mp->acls[i]));
1964 
1965  rv =
1966  acl_interface_set_inout_acl_list (am, sw_if_index, 0, out_acl_vec,
1967  &may_clear_sessions);
1968  rv = rv
1969  || acl_interface_set_inout_acl_list (am, sw_if_index, 1,
1970  in_acl_vec,
1971  &may_clear_sessions);
1972  vec_free (in_acl_vec);
1973  vec_free (out_acl_vec);
1974  clib_mem_set_heap (oldheap);
1975  }
1976  }
1977 
1978  REPLY_MACRO (VL_API_ACL_INTERFACE_SET_ACL_LIST_REPLY);
1979 }
1980 
1981 static void
1982 copy_acl_rule_to_api_rule (vl_api_acl_rule_t * api_rule, acl_rule_t * r)
1983 {
1984  api_rule->is_permit = r->is_permit;
1986  &api_rule->src_prefix.address);
1987  ip_address_encode (&r->dst, r->is_ipv6 ? IP46_TYPE_IP6 : IP46_TYPE_IP4,
1988  &api_rule->dst_prefix.address);
1989  api_rule->src_prefix.len = r->src_prefixlen;
1990  api_rule->dst_prefix.len = r->dst_prefixlen;
1991  api_rule->proto = r->proto;
1992  api_rule->srcport_or_icmptype_first = htons (r->src_port_or_type_first);
1993  api_rule->srcport_or_icmptype_last = htons (r->src_port_or_type_last);
1994  api_rule->dstport_or_icmpcode_first = htons (r->dst_port_or_code_first);
1995  api_rule->dstport_or_icmpcode_last = htons (r->dst_port_or_code_last);
1996  api_rule->tcp_flags_mask = r->tcp_flags_mask;
1997  api_rule->tcp_flags_value = r->tcp_flags_value;
1998 }
1999 
2000 static void
2002  acl_list_t * acl, u32 context)
2003 {
2005  vl_api_acl_rule_t *rules;
2006  int i;
2007  acl_rule_t *acl_rules = acl->rules;
2008  int msg_size = sizeof (*mp) + sizeof (mp->r[0]) * vec_len (acl_rules);
2009  void *oldheap = acl_set_heap (am);
2010 
2011  mp = vl_msg_api_alloc (msg_size);
2012  clib_memset (mp, 0, msg_size);
2013  mp->_vl_msg_id = ntohs (VL_API_ACL_DETAILS + am->msg_id_base);
2014 
2015  /* fill in the message */
2016  mp->context = context;
2017  mp->count = htonl (vec_len (acl_rules));
2018  mp->acl_index = htonl (acl - am->acls);
2019  memcpy (mp->tag, acl->tag, sizeof (mp->tag));
2020  // clib_memcpy (mp->r, acl->rules, acl->count * sizeof(acl->rules[0]));
2021  rules = mp->r;
2022  for (i = 0; i < vec_len (acl_rules); i++)
2023  {
2024  copy_acl_rule_to_api_rule (&rules[i], &acl_rules[i]);
2025  }
2026 
2027  clib_mem_set_heap (oldheap);
2028  vl_api_send_msg (reg, (u8 *) mp);
2029 }
2030 
2031 
2032 static void
2034 {
2035  acl_main_t *am = &acl_main;
2036  u32 acl_index;
2037  acl_list_t *acl;
2038  int rv = -1;
2039  vl_api_registration_t *reg;
2040 
2042  if (!reg)
2043  return;
2044 
2045  if (mp->acl_index == ~0)
2046  {
2047  /* *INDENT-OFF* */
2048  /* Just dump all ACLs */
2049  pool_foreach (acl, am->acls,
2050  ({
2051  send_acl_details(am, reg, acl, mp->context);
2052  }));
2053  /* *INDENT-ON* */
2054  }
2055  else
2056  {
2057  acl_index = ntohl (mp->acl_index);
2058  if (!pool_is_free_index (am->acls, acl_index))
2059  {
2060  acl = pool_elt_at_index (am->acls, acl_index);
2061  send_acl_details (am, reg, acl, mp->context);
2062  }
2063  }
2064 
2065  if (rv == -1)
2066  {
2067  /* FIXME API: should we signal an error here at all ? */
2068  return;
2069  }
2070 }
2071 
2072 static void
2074  vl_api_registration_t * reg,
2075  u32 sw_if_index, u32 context)
2076 {
2078  int msg_size;
2079  int n_input;
2080  int n_output;
2081  int count;
2082  int i = 0;
2083  void *oldheap = acl_set_heap (am);
2084 
2085  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
2086  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
2087 
2088  clib_mem_set_heap (oldheap);
2089 
2090  n_input = vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]);
2091  n_output = vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]);
2092  count = n_input + n_output;
2093 
2094  msg_size = sizeof (*mp);
2095  msg_size += sizeof (mp->acls[0]) * count;
2096 
2097  mp = vl_msg_api_alloc (msg_size);
2098  clib_memset (mp, 0, msg_size);
2099  mp->_vl_msg_id =
2100  ntohs (VL_API_ACL_INTERFACE_LIST_DETAILS + am->msg_id_base);
2101 
2102  /* fill in the message */
2103  mp->context = context;
2104  mp->sw_if_index = htonl (sw_if_index);
2105  mp->count = count;
2106  mp->n_input = n_input;
2107  for (i = 0; i < n_input; i++)
2108  {
2109  mp->acls[i] = htonl (am->input_acl_vec_by_sw_if_index[sw_if_index][i]);
2110  }
2111  for (i = 0; i < n_output; i++)
2112  {
2113  mp->acls[n_input + i] =
2114  htonl (am->output_acl_vec_by_sw_if_index[sw_if_index][i]);
2115  }
2116  vl_api_send_msg (reg, (u8 *) mp);
2117 }
2118 
2119 static void
2121  mp)
2122 {
2123  acl_main_t *am = &acl_main;
2124  vnet_sw_interface_t *swif;
2126 
2127  u32 sw_if_index;
2128  vl_api_registration_t *reg;
2129 
2131  if (!reg)
2132  return;
2133 
2134  if (mp->sw_if_index == ~0)
2135  {
2136  /* *INDENT-OFF* */
2137  pool_foreach (swif, im->sw_interfaces,
2138  ({
2139  send_acl_interface_list_details(am, reg, swif->sw_if_index, mp->context);
2140  }));
2141  /* *INDENT-ON* */
2142  }
2143  else
2144  {
2145  sw_if_index = ntohl (mp->sw_if_index);
2146  if (!pool_is_free_index (im->sw_interfaces, sw_if_index))
2147  send_acl_interface_list_details (am, reg, sw_if_index, mp->context);
2148  }
2149 }
2150 
2151 /* MACIP ACL API handlers */
2152 
2153 static void
2155 {
2157  acl_main_t *am = &acl_main;
2158  int rv;
2159  u32 acl_list_index = ~0;
2160  u32 acl_count = ntohl (mp->count);
2161  u32 expected_len = sizeof (*mp) + acl_count * sizeof (mp->r[0]);
2162 
2163  if (verify_message_len (mp, expected_len, "macip_acl_add"))
2164  {
2165  rv = macip_acl_add_list (acl_count, mp->r, &acl_list_index, mp->tag);
2166  }
2167  else
2168  {
2169  rv = VNET_API_ERROR_INVALID_VALUE;
2170  }
2171 
2172  /* *INDENT-OFF* */
2173  REPLY_MACRO2(VL_API_MACIP_ACL_ADD_REPLY,
2174  ({
2175  rmp->acl_index = htonl(acl_list_index);
2176  }));
2177  /* *INDENT-ON* */
2178 }
2179 
2180 static void
2182 {
2184  acl_main_t *am = &acl_main;
2185  int rv;
2186  u32 acl_list_index = ntohl (mp->acl_index);
2187  u32 acl_count = ntohl (mp->count);
2188  u32 expected_len = sizeof (*mp) + acl_count * sizeof (mp->r[0]);
2189 
2190  if (verify_message_len (mp, expected_len, "macip_acl_add_replace"))
2191  {
2192  rv = macip_acl_add_list (acl_count, mp->r, &acl_list_index, mp->tag);
2193  }
2194  else
2195  {
2196  rv = VNET_API_ERROR_INVALID_VALUE;
2197  }
2198 
2199  /* *INDENT-OFF* */
2200  REPLY_MACRO2(VL_API_MACIP_ACL_ADD_REPLACE_REPLY,
2201  ({
2202  rmp->acl_index = htonl(acl_list_index);
2203  }));
2204  /* *INDENT-ON* */
2205 }
2206 
2207 static void
2209 {
2210  acl_main_t *am = &acl_main;
2211  vl_api_macip_acl_del_reply_t *rmp;
2212  int rv;
2213 
2214  rv = macip_acl_del_list (ntohl (mp->acl_index));
2215 
2216  REPLY_MACRO (VL_API_MACIP_ACL_DEL_REPLY);
2217 }
2218 
2219 static void
2222 {
2223  acl_main_t *am = &acl_main;
2224  vl_api_macip_acl_interface_add_del_reply_t *rmp;
2225  int rv = -1;
2227  u32 sw_if_index = ntohl (mp->sw_if_index);
2228 
2229  if (pool_is_free_index (im->sw_interfaces, sw_if_index))
2230  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
2231  else
2232  rv =
2234  ntohl (mp->acl_index));
2235 
2236  REPLY_MACRO (VL_API_MACIP_ACL_INTERFACE_ADD_DEL_REPLY);
2237 }
2238 
2239 static void
2241  macip_acl_list_t * acl, u32 context)
2242 {
2244  vl_api_macip_acl_rule_t *rules;
2245  macip_acl_rule_t *r;
2246  int i;
2247  int msg_size = sizeof (*mp) + (acl ? sizeof (mp->r[0]) * acl->count : 0);
2248 
2249  mp = vl_msg_api_alloc (msg_size);
2250  clib_memset (mp, 0, msg_size);
2251  mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_DETAILS + am->msg_id_base);
2252 
2253  /* fill in the message */
2254  mp->context = context;
2255  if (acl)
2256  {
2257  memcpy (mp->tag, acl->tag, sizeof (mp->tag));
2258  mp->count = htonl (acl->count);
2259  mp->acl_index = htonl (acl - am->macip_acls);
2260  rules = mp->r;
2261  for (i = 0; i < acl->count; i++)
2262  {
2263  r = &acl->rules[i];
2264  rules[i].is_permit = r->is_permit;
2266  rules[i].src_mac);
2268  rules[i].src_mac_mask);
2271  &rules[i].src_prefix.address);
2272  rules[i].src_prefix.len = r->src_prefixlen;
2273  }
2274  }
2275  else
2276  {
2277  /* No martini, no party - no ACL applied to this interface. */
2278  mp->acl_index = ~0;
2279  mp->count = 0;
2280  }
2281 
2282  vl_api_send_msg (reg, (u8 *) mp);
2283 }
2284 
2285 
2286 static void
2288 {
2289  acl_main_t *am = &acl_main;
2290  macip_acl_list_t *acl;
2291 
2292  vl_api_registration_t *reg;
2293 
2295  if (!reg)
2296  return;
2297 
2298  if (mp->acl_index == ~0)
2299  {
2300  /* Just dump all ACLs for now, with sw_if_index = ~0 */
2301  /* *INDENT-OFF* */
2302  pool_foreach (acl, am->macip_acls,
2303  ({
2304  send_macip_acl_details (am, reg, acl, mp->context);
2305  }));
2306  /* *INDENT-ON* */
2307  }
2308  else
2309  {
2310  u32 acl_index = ntohl (mp->acl_index);
2311  if (!pool_is_free_index (am->macip_acls, acl_index))
2312  {
2313  acl = pool_elt_at_index (am->macip_acls, acl_index);
2314  send_macip_acl_details (am, reg, acl, mp->context);
2315  }
2316  }
2317 }
2318 
2319 static void
2321  mp)
2322 {
2323  acl_main_t *am = &acl_main;
2326  int msg_size = sizeof (*rmp) + sizeof (rmp->acls[0]) * count;
2327  vl_api_registration_t *reg;
2328  int i;
2329 
2331  if (!reg)
2332  return;
2333 
2334  rmp = vl_msg_api_alloc (msg_size);
2335  clib_memset (rmp, 0, msg_size);
2336  rmp->_vl_msg_id =
2337  ntohs (VL_API_MACIP_ACL_INTERFACE_GET_REPLY + am->msg_id_base);
2338  rmp->context = mp->context;
2339  rmp->count = htonl (count);
2340  for (i = 0; i < count; i++)
2341  {
2342  rmp->acls[i] = htonl (am->macip_acl_by_sw_if_index[i]);
2343  }
2344 
2345  vl_api_send_msg (reg, (u8 *) rmp);
2346 }
2347 
2348 static void
2350  vl_api_registration_t * reg,
2351  u32 sw_if_index,
2352  u32 acl_index, u32 context)
2353 {
2355  /* at this time there is only ever 1 mac ip acl per interface */
2356  int msg_size = sizeof (*rmp) + sizeof (rmp->acls[0]);
2357 
2358  rmp = vl_msg_api_alloc (msg_size);
2359  clib_memset (rmp, 0, msg_size);
2360  rmp->_vl_msg_id =
2361  ntohs (VL_API_MACIP_ACL_INTERFACE_LIST_DETAILS + am->msg_id_base);
2362 
2363  /* fill in the message */
2364  rmp->context = context;
2365  rmp->count = 1;
2366  rmp->sw_if_index = htonl (sw_if_index);
2367  rmp->acls[0] = htonl (acl_index);
2368 
2369  vl_api_send_msg (reg, (u8 *) rmp);
2370 }
2371 
2372 static void
2375 {
2376  vl_api_registration_t *reg;
2377  acl_main_t *am = &acl_main;
2378  u32 sw_if_index = ntohl (mp->sw_if_index);
2379 
2381  if (!reg)
2382  return;
2383 
2384  if (sw_if_index == ~0)
2385  {
2386  vec_foreach_index (sw_if_index, am->macip_acl_by_sw_if_index)
2387  {
2388  if (~0 != am->macip_acl_by_sw_if_index[sw_if_index])
2389  {
2390  send_macip_acl_interface_list_details (am, reg, sw_if_index,
2392  [sw_if_index],
2393  mp->context);
2394  }
2395  }
2396  }
2397  else
2398  {
2399  if (vec_len (am->macip_acl_by_sw_if_index) > sw_if_index)
2400  {
2401  send_macip_acl_interface_list_details (am, reg, sw_if_index,
2403  [sw_if_index], mp->context);
2404  }
2405  }
2406 }
2407 
2408 static void
2411 {
2412  acl_main_t *am = &acl_main;
2413  vl_api_acl_interface_set_etype_whitelist_reply_t *rmp;
2414  int rv = 0;
2415  int i;
2417  u32 sw_if_index = ntohl (mp->sw_if_index);
2418  u16 *vec_in = 0, *vec_out = 0;
2419  void *oldheap = acl_set_heap (am);
2420 
2421  if (pool_is_free_index (im->sw_interfaces, sw_if_index))
2422  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
2423  else
2424  {
2425  for (i = 0; i < mp->count; i++)
2426  {
2427  if (i < mp->n_input)
2428  vec_add1 (vec_in, ntohs (mp->whitelist[i]));
2429  else
2430  vec_add1 (vec_out, ntohs (mp->whitelist[i]));
2431  }
2432  rv = acl_set_etype_whitelists (am, sw_if_index, vec_in, vec_out);
2433  }
2434 
2435  clib_mem_set_heap (oldheap);
2436  REPLY_MACRO (VL_API_ACL_INTERFACE_SET_ETYPE_WHITELIST_REPLY);
2437 }
2438 
2439 static void
2441  vl_api_registration_t * reg,
2442  u32 sw_if_index, u32 context)
2443 {
2445  int msg_size;
2446  int n_input = 0;
2447  int n_output = 0;
2448  int count = 0;
2449  int i = 0;
2450 
2451  u16 *whitelist_in = 0;
2452  u16 *whitelist_out = 0;
2453 
2454  if (intf_has_etype_whitelist (am, sw_if_index, 0))
2455  whitelist_out =
2457 
2458  if (intf_has_etype_whitelist (am, sw_if_index, 1))
2459  whitelist_in =
2460  vec_elt (am->input_etype_whitelist_by_sw_if_index, sw_if_index);
2461 
2462  if ((0 == whitelist_in) && (0 == whitelist_out))
2463  return; /* nothing to do */
2464 
2465  void *oldheap = acl_set_heap (am);
2466 
2467  n_input = vec_len (whitelist_in);
2468  n_output = vec_len (whitelist_out);
2469  count = n_input + n_output;
2470 
2471  msg_size = sizeof (*mp);
2472  msg_size += sizeof (mp->whitelist[0]) * count;
2473 
2474  mp = vl_msg_api_alloc (msg_size);
2475  clib_memset (mp, 0, msg_size);
2476  mp->_vl_msg_id =
2477  ntohs (VL_API_ACL_INTERFACE_ETYPE_WHITELIST_DETAILS + am->msg_id_base);
2478 
2479  /* fill in the message */
2480  mp->context = context;
2481  mp->sw_if_index = htonl (sw_if_index);
2482  mp->count = count;
2483  mp->n_input = n_input;
2484  for (i = 0; i < n_input; i++)
2485  {
2486  mp->whitelist[i] = htons (whitelist_in[i]);
2487  }
2488  for (i = 0; i < n_output; i++)
2489  {
2490  mp->whitelist[n_input + i] = htons (whitelist_out[i]);
2491  }
2492  clib_mem_set_heap (oldheap);
2493  vl_api_send_msg (reg, (u8 *) mp);
2494 }
2495 
2496 
2497 static void
2500 {
2501  acl_main_t *am = &acl_main;
2502  vnet_sw_interface_t *swif;
2504 
2505  u32 sw_if_index;
2506  vl_api_registration_t *reg;
2507 
2509  if (!reg)
2510  return;
2511 
2512  if (mp->sw_if_index == ~0)
2513  {
2514  /* *INDENT-OFF* */
2515  pool_foreach (swif, im->sw_interfaces,
2516  ({
2517  send_acl_interface_etype_whitelist_details(am, reg, swif->sw_if_index, mp->context);
2518  }));
2519  /* *INDENT-ON* */
2520  }
2521  else
2522  {
2523  sw_if_index = ntohl (mp->sw_if_index);
2524  if (!pool_is_free_index (im->sw_interfaces, sw_if_index))
2525  send_acl_interface_etype_whitelist_details (am, reg, sw_if_index,
2526  mp->context);
2527  }
2528 }
2529 
2530 static void
2531 acl_set_timeout_sec (int timeout_type, u32 value)
2532 {
2533  acl_main_t *am = &acl_main;
2534  clib_time_t *ct = &am->vlib_main->clib_time;
2535 
2536  if (timeout_type < ACL_N_TIMEOUTS)
2537  {
2538  am->session_timeout_sec[timeout_type] = value;
2539  }
2540  else
2541  {
2542  clib_warning ("Unknown timeout type %d", timeout_type);
2543  return;
2544  }
2545  am->session_timeout[timeout_type] =
2546  (u64) (((f64) value) / ct->seconds_per_clock);
2547 }
2548 
2549 static void
2551 {
2552  acl_main_t *am = &acl_main;
2554 }
2555 
2556 static int
2558 {
2559  acl_main_t *am = &acl_main;
2560 
2561  if ((eh < 256) && (value < 2))
2562  {
2564  clib_bitmap_set (am->fa_ipv6_known_eh_bitmap, eh, value);
2565  return 1;
2566  }
2567  else
2568  return 0;
2569 }
2570 
2571 
2572 static clib_error_t *
2574 {
2575  acl_main_t *am = &acl_main;
2576  if (0 == am->acl_mheap)
2577  {
2578  /* ACL heap is not initialized, so definitely nothing to do. */
2579  return 0;
2580  }
2581  if (0 == is_add)
2582  {
2583  int may_clear_sessions = 1;
2586  sw_if_index);
2587  /* also unapply any ACLs in case the users did not do so. */
2588  macip_acl_interface_del_acl (am, sw_if_index);
2589  acl_interface_reset_inout_acls (sw_if_index, 0, &may_clear_sessions);
2590  acl_interface_reset_inout_acls (sw_if_index, 1, &may_clear_sessions);
2591  }
2592  return 0;
2593 }
2594 
2596 
2597 
2598 
2599 static clib_error_t *
2601  unformat_input_t * input, vlib_cli_command_t * cmd)
2602 {
2603  clib_error_t *error = 0;
2604  u32 timeout = 0;
2605  u32 val = 0;
2606  u32 eh_val = 0;
2607  uword memory_size = 0;
2608  acl_main_t *am = &acl_main;
2609 
2610  if (unformat (input, "skip-ipv6-extension-header %u %u", &eh_val, &val))
2611  {
2612  if (!acl_set_skip_ipv6_eh (eh_val, val))
2613  {
2614  error = clib_error_return (0, "expecting eh=0..255, value=0..1");
2615  }
2616  goto done;
2617  }
2618  if (unformat (input, "use-hash-acl-matching %u", &val))
2619  {
2620  am->use_hash_acl_matching = (val != 0);
2621  goto done;
2622  }
2623  if (unformat (input, "l4-match-nonfirst-fragment %u", &val))
2624  {
2625  am->l4_match_nonfirst_fragment = (val != 0);
2626  goto done;
2627  }
2628  if (unformat (input, "reclassify-sessions %u", &val))
2629  {
2630  am->reclassify_sessions = (val != 0);
2631  goto done;
2632  }
2633  if (unformat (input, "event-trace"))
2634  {
2635  if (!unformat (input, "%u", &val))
2636  {
2637  error = clib_error_return (0,
2638  "expecting trace level, got `%U`",
2639  format_unformat_error, input);
2640  goto done;
2641  }
2642  else
2643  {
2644  am->trace_acl = val;
2645  goto done;
2646  }
2647  }
2648  if (unformat (input, "heap"))
2649  {
2650  if (unformat (input, "main"))
2651  {
2652  if (unformat (input, "validate %u", &val))
2654  else if (unformat (input, "trace %u", &val))
2656  goto done;
2657  }
2658  else if (unformat (input, "hash"))
2659  {
2660  if (unformat (input, "validate %u", &val))
2662  else if (unformat (input, "trace %u", &val))
2664  goto done;
2665  }
2666  goto done;
2667  }
2668  if (unformat (input, "session"))
2669  {
2670  if (unformat (input, "table"))
2671  {
2672  /* The commands here are for tuning/testing. No user-serviceable parts inside */
2673  if (unformat (input, "max-entries"))
2674  {
2675  if (!unformat (input, "%u", &val))
2676  {
2677  error = clib_error_return (0,
2678  "expecting maximum number of entries, got `%U`",
2679  format_unformat_error, input);
2680  goto done;
2681  }
2682  else
2683  {
2685  goto done;
2686  }
2687  }
2688  if (unformat (input, "hash-table-buckets"))
2689  {
2690  if (!unformat (input, "%u", &val))
2691  {
2692  error = clib_error_return (0,
2693  "expecting maximum number of hash table buckets, got `%U`",
2694  format_unformat_error, input);
2695  goto done;
2696  }
2697  else
2698  {
2700  goto done;
2701  }
2702  }
2703  if (unformat (input, "hash-table-memory"))
2704  {
2705  if (!unformat (input, "%U", unformat_memory_size, &memory_size))
2706  {
2707  error = clib_error_return (0,
2708  "expecting maximum amount of hash table memory, got `%U`",
2709  format_unformat_error, input);
2710  goto done;
2711  }
2712  else
2713  {
2715  goto done;
2716  }
2717  }
2718  if (unformat (input, "event-trace"))
2719  {
2720  if (!unformat (input, "%u", &val))
2721  {
2722  error = clib_error_return (0,
2723  "expecting trace level, got `%U`",
2724  format_unformat_error, input);
2725  goto done;
2726  }
2727  else
2728  {
2729  am->trace_sessions = val;
2730  goto done;
2731  }
2732  }
2733  goto done;
2734  }
2735  if (unformat (input, "timeout"))
2736  {
2737  if (unformat (input, "udp"))
2738  {
2739  if (unformat (input, "idle"))
2740  {
2741  if (!unformat (input, "%u", &timeout))
2742  {
2743  error = clib_error_return (0,
2744  "expecting timeout value in seconds, got `%U`",
2746  input);
2747  goto done;
2748  }
2749  else
2750  {
2752  goto done;
2753  }
2754  }
2755  }
2756  if (unformat (input, "tcp"))
2757  {
2758  if (unformat (input, "idle"))
2759  {
2760  if (!unformat (input, "%u", &timeout))
2761  {
2762  error = clib_error_return (0,
2763  "expecting timeout value in seconds, got `%U`",
2765  input);
2766  goto done;
2767  }
2768  else
2769  {
2771  goto done;
2772  }
2773  }
2774  if (unformat (input, "transient"))
2775  {
2776  if (!unformat (input, "%u", &timeout))
2777  {
2778  error = clib_error_return (0,
2779  "expecting timeout value in seconds, got `%U`",
2781  input);
2782  goto done;
2783  }
2784  else
2785  {
2787  timeout);
2788  goto done;
2789  }
2790  }
2791  }
2792  goto done;
2793  }
2794  }
2795 done:
2796  return error;
2797 }
2798 
2799 static u8 *
2800 my_format_mac_address (u8 * s, va_list * args)
2801 {
2802  u8 *a = va_arg (*args, u8 *);
2803  return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
2804  a[0], a[1], a[2], a[3], a[4], a[5]);
2805 }
2806 
2807 static inline u8 *
2808 my_macip_acl_rule_t_pretty_format (u8 * out, va_list * args)
2809 {
2810  macip_acl_rule_t *a = va_arg (*args, macip_acl_rule_t *);
2811 
2812  out = format (out, "%s action %d ip %U/%d mac %U mask %U",
2813  a->is_ipv6 ? "ipv6" : "ipv4", a->is_permit,
2816  a->src_prefixlen,
2819  return (out);
2820 }
2821 
2822 static void
2823 macip_acl_print (acl_main_t * am, u32 macip_acl_index)
2824 {
2825  vlib_main_t *vm = am->vlib_main;
2826  int i;
2827 
2828  /* Don't try to print someone else's memory */
2829  if (macip_acl_index >= vec_len (am->macip_acls))
2830  return;
2831 
2832  macip_acl_list_t *a = vec_elt_at_index (am->macip_acls, macip_acl_index);
2833  int free_pool_slot = pool_is_free_index (am->macip_acls, macip_acl_index);
2834 
2835  vlib_cli_output (vm,
2836  "MACIP acl_index: %d, count: %d (true len %d) tag {%s} is free pool slot: %d\n",
2837  macip_acl_index, a->count, vec_len (a->rules), a->tag,
2838  free_pool_slot);
2839  vlib_cli_output (vm,
2840  " ip4_table_index %d, ip6_table_index %d, l2_table_index %d\n",
2842  vlib_cli_output (vm,
2843  " out_ip4_table_index %d, out_ip6_table_index %d, out_l2_table_index %d\n",
2845  a->out_l2_table_index);
2846  for (i = 0; i < vec_len (a->rules); i++)
2847  vlib_cli_output (vm, " rule %d: %U\n", i,
2849  vec_elt_at_index (a->rules, i));
2850 
2851 }
2852 
2853 static clib_error_t *
2855  unformat_input_t * input,
2856  vlib_cli_command_t * cmd)
2857 {
2858  unformat_input_t _line_input, *line_input = &_line_input;
2859  u32 sw_if_index, is_add, is_input, acl_index;
2860 
2861  is_add = is_input = 1;
2862  acl_index = sw_if_index = ~0;
2863 
2864  if (!unformat_user (input, unformat_line_input, line_input))
2865  return 0;
2866 
2867  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2868  {
2869  if (unformat (line_input, "%U",
2871  &sw_if_index))
2872  ;
2873  else if (unformat (line_input, "add"))
2874  is_add = 1;
2875  else if (unformat (line_input, "del"))
2876  is_add = 0;
2877  else if (unformat (line_input, "acl %d", &acl_index))
2878  ;
2879  else if (unformat (line_input, "input"))
2880  is_input = 1;
2881  else if (unformat (line_input, "output"))
2882  is_input = 0;
2883  else
2884  break;
2885  }
2886 
2887  if (~0 == sw_if_index)
2888  return (clib_error_return (0, "invalid interface"));
2889  if (~0 == acl_index)
2890  return (clib_error_return (0, "invalid acl"));
2891 
2892  acl_interface_add_del_inout_acl (sw_if_index, is_add, is_input, acl_index);
2893 
2894  unformat_free (line_input);
2895  return (NULL);
2896 }
2897 
2898 #define vec_validate_acl_rules(v, idx) \
2899  do { \
2900  if (vec_len(v) < idx+1) { \
2901  vec_validate(v, idx); \
2902  v[idx].is_permit = 0x1; \
2903  v[idx].srcport_or_icmptype_last = 0xffff; \
2904  v[idx].dstport_or_icmpcode_last = 0xffff; \
2905  } \
2906  } while (0)
2907 
2908 static clib_error_t *
2910  unformat_input_t * input, vlib_cli_command_t * cmd)
2911 {
2912  unformat_input_t _line_input, *line_input = &_line_input;
2913  vl_api_acl_rule_t *rules = 0;
2914  int rv;
2915  int rule_idx = 0;
2916  int n_rules_override = -1;
2917  u32 proto = 0;
2918  u32 port1 = 0;
2919  u32 port2 = 0;
2920  u32 action = 0;
2921  u32 tcpflags, tcpmask;
2922  u32 src_prefix_length = 0, dst_prefix_length = 0;
2923  ip46_address_t src, dst;
2924  u8 *tag = (u8 *) "cli";
2925 
2926  if (!unformat_user (input, unformat_line_input, line_input))
2927  return 0;
2928 
2929  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2930  {
2931  if (unformat (line_input, "permit+reflect"))
2932  {
2933  vec_validate_acl_rules (rules, rule_idx);
2934  rules[rule_idx].is_permit = 2;
2935  }
2936  else if (unformat (line_input, "permit"))
2937  {
2938  vec_validate_acl_rules (rules, rule_idx);
2939  rules[rule_idx].is_permit = 1;
2940  }
2941  else if (unformat (line_input, "deny"))
2942  {
2943  vec_validate_acl_rules (rules, rule_idx);
2944  rules[rule_idx].is_permit = 0;
2945  }
2946  else if (unformat (line_input, "count %d", &n_rules_override))
2947  {
2948  /* we will use this later */
2949  }
2950  else if (unformat (line_input, "action %d", &action))
2951  {
2952  vec_validate_acl_rules (rules, rule_idx);
2953  rules[rule_idx].is_permit = action;
2954  }
2955  else if (unformat (line_input, "src %U/%d",
2957  &src_prefix_length))
2958  {
2959  vec_validate_acl_rules (rules, rule_idx);
2961  &rules[rule_idx].src_prefix.address);
2962  rules[rule_idx].src_prefix.address.af = ADDRESS_IP4;
2963  rules[rule_idx].src_prefix.len = src_prefix_length;
2964  }
2965  else if (unformat (line_input, "dst %U/%d",
2967  &dst_prefix_length))
2968  {
2969  vec_validate_acl_rules (rules, rule_idx);
2971  &rules[rule_idx].dst_prefix.address);
2972  rules[rule_idx].dst_prefix.address.af = ADDRESS_IP4;
2973  rules[rule_idx].dst_prefix.len = dst_prefix_length;
2974  }
2975  else if (unformat (line_input, "sport %d-%d", &port1, &port2))
2976  {
2977  vec_validate_acl_rules (rules, rule_idx);
2978  rules[rule_idx].srcport_or_icmptype_first = htons (port1);
2979  rules[rule_idx].srcport_or_icmptype_last = htons (port2);
2980  }
2981  else if (unformat (line_input, "sport %d", &port1))
2982  {
2983  vec_validate_acl_rules (rules, rule_idx);
2984  rules[rule_idx].srcport_or_icmptype_first = htons (port1);
2985  rules[rule_idx].srcport_or_icmptype_last = htons (port1);
2986  }
2987  else if (unformat (line_input, "dport %d-%d", &port1, &port2))
2988  {
2989  vec_validate_acl_rules (rules, rule_idx);
2990  rules[rule_idx].dstport_or_icmpcode_first = htons (port1);
2991  rules[rule_idx].dstport_or_icmpcode_last = htons (port2);
2992  }
2993  else if (unformat (line_input, "dport %d", &port1))
2994  {
2995  vec_validate_acl_rules (rules, rule_idx);
2996  rules[rule_idx].dstport_or_icmpcode_first = htons (port1);
2997  rules[rule_idx].dstport_or_icmpcode_last = htons (port1);
2998  }
2999  else if (unformat (line_input, "tcpflags %d %d", &tcpflags, &tcpmask))
3000  {
3001  vec_validate_acl_rules (rules, rule_idx);
3002  rules[rule_idx].tcp_flags_value = tcpflags;
3003  rules[rule_idx].tcp_flags_mask = tcpmask;
3004  }
3005  else
3006  if (unformat (line_input, "tcpflags %d mask %d", &tcpflags, &tcpmask))
3007  {
3008  vec_validate_acl_rules (rules, rule_idx);
3009  rules[rule_idx].tcp_flags_value = tcpflags;
3010  rules[rule_idx].tcp_flags_mask = tcpmask;
3011  }
3012  else if (unformat (line_input, "proto %d", &proto))
3013  {
3014  vec_validate_acl_rules (rules, rule_idx);
3015  rules[rule_idx].proto = proto;
3016  }
3017  else if (unformat (line_input, "tag %s", &tag))
3018  {
3019  }
3020  else if (unformat (line_input, ","))
3021  {
3022  rule_idx++;
3023  vec_validate_acl_rules (rules, rule_idx);
3024  }
3025  else
3026  break;
3027  }
3028 
3029  u32 acl_index = ~0;
3030 
3031  rv = acl_add_list (vec_len (rules), rules, &acl_index, tag);
3032 
3033  vec_free (rules);
3034 
3035  if (rv)
3036  return (clib_error_return (0, "failed"));
3037 
3038  vlib_cli_output (vm, "ACL index:%d", acl_index);
3039 
3040  return (NULL);
3041 }
3042 
3043 static clib_error_t *
3046  input, vlib_cli_command_t * cmd)
3047 {
3048  clib_error_t *error = 0;
3049  acl_main_t *am = &acl_main;
3050  int i;
3051  u32 acl_index = ~0;
3052 
3053  (void) unformat (input, "index %u", &acl_index);
3054 
3055  for (i = 0; i < vec_len (am->macip_acls); i++)
3056  {
3057  /* Don't attempt to show the ACLs that do not exist */
3058  if (pool_is_free_index (am->macip_acls, i))
3059  continue;
3060 
3061  if ((acl_index != ~0) && (acl_index != i))
3062  {
3063  continue;
3064  }
3065 
3066  macip_acl_print (am, i);
3067  if (i < vec_len (am->sw_if_index_vec_by_macip_acl))
3068  {
3069  vlib_cli_output (vm, " applied on sw_if_index(s): %U\n",
3070  format_vec32,
3072  "%d");
3073  }
3074  }
3075 
3076  return error;
3077 }
3078 
3079 static clib_error_t *
3082  input, vlib_cli_command_t * cmd)
3083 {
3084  clib_error_t *error = 0;
3085  acl_main_t *am = &acl_main;
3086  int i;
3087  for (i = 0; i < vec_len (am->macip_acl_by_sw_if_index); i++)
3088  {
3089  vlib_cli_output (vm, " sw_if_index %d: %d\n", i,
3091  }
3092  return error;
3093 }
3094 
3095 static void
3097 {
3098  u32 i;
3099  vlib_main_t *vm = am->vlib_main;
3100 
3101  for (i = 0; i < vec_len (am->acls); i++)
3102  {
3103  if (acl_is_not_defined (am, i))
3104  {
3105  /* don't attempt to show the ACLs that do not exist */
3106  continue;
3107  }
3108  if ((acl_index != ~0) && (acl_index != i))
3109  {
3110  continue;
3111  }
3112  acl_print_acl (vm, am, i);
3113 
3114  if (i < vec_len (am->input_sw_if_index_vec_by_acl))
3115  {
3116  vlib_cli_output (vm, " applied inbound on sw_if_index: %U\n",
3118  "%d");
3119  }
3120  if (i < vec_len (am->output_sw_if_index_vec_by_acl))
3121  {
3122  vlib_cli_output (vm, " applied outbound on sw_if_index: %U\n",
3124  "%d");
3125  }
3126  if (i < vec_len (am->lc_index_vec_by_acl))
3127  {
3128  vlib_cli_output (vm, " used in lookup context index: %U\n",
3129  format_vec32, am->lc_index_vec_by_acl[i], "%d");
3130  }
3131  }
3132 }
3133 
3134 static clib_error_t *
3136  unformat_input_t * input, vlib_cli_command_t * cmd)
3137 {
3138  clib_error_t *error = 0;
3139  acl_main_t *am = &acl_main;
3140 
3141  u32 acl_index = ~0;
3142  (void) unformat (input, "index %u", &acl_index);
3143 
3144  acl_plugin_show_acl (am, acl_index);
3145  return error;
3146 }
3147 
3148 static clib_error_t *
3150  unformat_input_t * input,
3151  vlib_cli_command_t * cmd)
3152 {
3153  clib_error_t *error = 0;
3154 
3155  u32 lc_index = ~0;
3156  (void) unformat (input, "index %u", &lc_index);
3157 
3158  acl_plugin_show_lookup_context (lc_index);
3159  return error;
3160 }
3161 
3162 static clib_error_t *
3164  unformat_input_t * input,
3165  vlib_cli_command_t * cmd)
3166 {
3167  clib_error_t *error = 0;
3168 
3169  u32 lc_index = ~0;
3170  (void) unformat (input, "index %u", &lc_index);
3171 
3172  acl_plugin_show_lookup_user (lc_index);
3173  return error;
3174 }
3175 
3176 
3177 static void
3179  int detail)
3180 {
3181  vlib_main_t *vm = am->vlib_main;
3182  u32 swi;
3183  u32 *pj;
3184  for (swi = 0; (swi < vec_len (am->input_acl_vec_by_sw_if_index)) ||
3185  (swi < vec_len (am->output_acl_vec_by_sw_if_index)); swi++)
3186  {
3187  /* if we need a particular interface, skip all the others */
3188  if ((sw_if_index != ~0) && (sw_if_index != swi))
3189  continue;
3190 
3191  vlib_cli_output (vm, "sw_if_index %d:\n", swi);
3193  vlib_cli_output (vm, " input policy epoch: %x\n",
3195  swi));
3197  vlib_cli_output (vm, " output policy epoch: %x\n",
3199  swi));
3200 
3201 
3202  if (intf_has_etype_whitelist (am, swi, 1))
3203  {
3204  vlib_cli_output (vm, " input etype whitelist: %U", format_vec16,
3206  "%04x");
3207  }
3208  if (intf_has_etype_whitelist (am, swi, 0))
3209  {
3210  vlib_cli_output (vm, " output etype whitelist: %U", format_vec16,
3212  "%04x");
3213  }
3214 
3215  if ((swi < vec_len (am->input_acl_vec_by_sw_if_index)) &&
3216  (vec_len (am->input_acl_vec_by_sw_if_index[swi]) > 0))
3217  {
3218  vlib_cli_output (vm, " input acl(s): %U", format_vec32,
3219  am->input_acl_vec_by_sw_if_index[swi], "%d");
3220  if (show_acl)
3221  {
3222  vlib_cli_output (vm, "\n");
3224  {
3225  acl_print_acl (vm, am, *pj);
3226  }
3227  vlib_cli_output (vm, "\n");
3228  }
3229  }
3230 
3231  if ((swi < vec_len (am->output_acl_vec_by_sw_if_index)) &&
3232  (vec_len (am->output_acl_vec_by_sw_if_index[swi]) > 0))
3233  {
3234  vlib_cli_output (vm, " output acl(s): %U", format_vec32,
3235  am->output_acl_vec_by_sw_if_index[swi], "%d");
3236  if (show_acl)
3237  {
3238  vlib_cli_output (vm, "\n");
3240  {
3241  acl_print_acl (vm, am, *pj);
3242  }
3243  vlib_cli_output (vm, "\n");
3244  }
3245  }
3246  if (detail && (swi < vec_len (am->input_lc_index_by_sw_if_index)))
3247  {
3248  vlib_cli_output (vm, " input lookup context index: %d",
3250  }
3251  if (detail && (swi < vec_len (am->output_lc_index_by_sw_if_index)))
3252  {
3253  vlib_cli_output (vm, " output lookup context index: %d",
3255  }
3256  }
3257 
3258 }
3259 
3260 
3261 static clib_error_t *
3263  unformat_input_t * input,
3264  vlib_cli_command_t * cmd)
3265 {
3266  clib_error_t *error = 0;
3267  u64 five_tuple[6] = { 0, 0, 0, 0, 0, 0 };
3268 
3269  if (unformat
3270  (input, "%llx %llx %llx %llx %llx %llx", &five_tuple[0], &five_tuple[1],
3271  &five_tuple[2], &five_tuple[3], &five_tuple[4], &five_tuple[5]))
3272  vlib_cli_output (vm, "5-tuple structure decode: %U\n\n",
3273  format_acl_plugin_5tuple, five_tuple);
3274  else
3275  error = clib_error_return (0, "expecting 6 hex integers");
3276  return error;
3277 }
3278 
3279 
3280 static clib_error_t *
3283  input, vlib_cli_command_t * cmd)
3284 {
3285  clib_error_t *error = 0;
3286  acl_main_t *am = &acl_main;
3287 
3288  u32 sw_if_index = ~0;
3289  (void) unformat (input, "sw_if_index %u", &sw_if_index);
3290  int show_acl = unformat (input, "acl");
3291  int detail = unformat (input, "detail");
3292 
3293  acl_plugin_show_interface (am, sw_if_index, show_acl, detail);
3294  return error;
3295 }
3296 
3297 static clib_error_t *
3299  unformat_input_t * input,
3300  vlib_cli_command_t * cmd)
3301 {
3302  clib_error_t *error = 0;
3303  acl_main_t *am = &acl_main;
3304 
3305  vlib_cli_output (vm, "ACL plugin main heap statistics:\n");
3306  if (am->acl_mheap)
3307  {
3308  vlib_cli_output (vm, " %U\n", format_mheap, am->acl_mheap, 1);
3309  }
3310  else
3311  {
3312  vlib_cli_output (vm, " Not initialized\n");
3313  }
3314  vlib_cli_output (vm, "ACL hash lookup support heap statistics:\n");
3315  if (am->hash_lookup_mheap)
3316  {
3317  vlib_cli_output (vm, " %U\n", format_mheap, am->hash_lookup_mheap, 1);
3318  }
3319  else
3320  {
3321  vlib_cli_output (vm, " Not initialized\n");
3322  }
3323  return error;
3324 }
3325 
3326 static void
3328  u32 show_session_thread_id,
3329  u32 show_session_session_index)
3330 {
3331  vlib_main_t *vm = am->vlib_main;
3332  u16 wk;
3334  vnet_sw_interface_t *swif;
3335  u64 now = clib_cpu_time_now ();
3336  u64 clocks_per_second = am->vlib_main->clib_time.clocks_per_second;
3337 
3338  {
3339  u64 n_adds = am->fa_session_total_adds;
3340  u64 n_dels = am->fa_session_total_dels;
3341  u64 n_deact = am->fa_session_total_deactivations;
3342  vlib_cli_output (vm, "Sessions total: add %lu - del %lu = %lu", n_adds,
3343  n_dels, n_adds - n_dels);
3344  vlib_cli_output (vm, "Sessions active: add %lu - deact %lu = %lu", n_adds,
3345  n_deact, n_adds - n_deact);
3346  vlib_cli_output (vm, "Sessions being purged: deact %lu - del %lu = %lu",
3347  n_deact, n_dels, n_deact - n_dels);
3348  }
3349  vlib_cli_output (vm, "now: %lu clocks per second: %lu", now,
3350  clocks_per_second);
3351  vlib_cli_output (vm, "\n\nPer-thread data:");
3352  for (wk = 0; wk < vec_len (am->per_worker_data); wk++)
3353  {
3355  vlib_cli_output (vm, "Thread #%d:", wk);
3356  if (show_session_thread_id == wk
3357  && show_session_session_index < pool_len (pw->fa_sessions_pool))
3358  {
3359  vlib_cli_output (vm, " session index %u:",
3360  show_session_session_index);
3361  fa_session_t *sess =
3362  pw->fa_sessions_pool + show_session_session_index;
3363  u64 *m = (u64 *) & sess->info;
3364  vlib_cli_output (vm,
3365  " info: %016llx %016llx %016llx %016llx %016llx %016llx",
3366  m[0], m[1], m[2], m[3], m[4], m[5]);
3367  vlib_cli_output (vm, " sw_if_index: %u", sess->sw_if_index);
3368  vlib_cli_output (vm, " tcp_flags_seen: %x",
3369  sess->tcp_flags_seen.as_u16);
3370  vlib_cli_output (vm, " last active time: %lu",
3371  sess->last_active_time);
3372  vlib_cli_output (vm, " thread index: %u", sess->thread_index);
3373  vlib_cli_output (vm, " link enqueue time: %lu",
3374  sess->link_enqueue_time);
3375  vlib_cli_output (vm, " link next index: %u",
3376  sess->link_next_idx);
3377  vlib_cli_output (vm, " link prev index: %u",
3378  sess->link_prev_idx);
3379  vlib_cli_output (vm, " link list id: %u", sess->link_list_id);
3380  }
3381  vlib_cli_output (vm, " connection add/del stats:", wk);
3382  /* *INDENT-OFF* */
3383  pool_foreach (swif, im->sw_interfaces,
3384  ({
3385  u32 sw_if_index = swif->sw_if_index;
3386  u64 n_adds =
3387  (sw_if_index < vec_len (pw->fa_session_adds_by_sw_if_index) ?
3388  pw->fa_session_adds_by_sw_if_index[sw_if_index] :
3389  0);
3390  u64 n_dels =
3391  (sw_if_index < vec_len (pw->fa_session_dels_by_sw_if_index) ?
3392  pw->fa_session_dels_by_sw_if_index[sw_if_index] :
3393  0);
3394  u64 n_epoch_changes =
3395  (sw_if_index < vec_len (pw->fa_session_epoch_change_by_sw_if_index) ?
3396  pw->fa_session_epoch_change_by_sw_if_index[sw_if_index] :
3397  0);
3398  vlib_cli_output (vm,
3399  " sw_if_index %d: add %lu - del %lu = %lu; epoch chg: %lu",
3400  sw_if_index,
3401  n_adds,
3402  n_dels,
3403  n_adds -
3404  n_dels,
3405  n_epoch_changes);
3406  }));
3407  /* *INDENT-ON* */
3408 
3409  vlib_cli_output (vm, " connection timeout type lists:", wk);
3410  u8 tt = 0;
3411  for (tt = 0; tt < ACL_N_TIMEOUTS; tt++)
3412  {
3413  u32 head_session_index = pw->fa_conn_list_head[tt];
3414  vlib_cli_output (vm, " fa_conn_list_head[%d]: %d", tt,
3415  head_session_index);
3416  if (~0 != head_session_index)
3417  {
3418  fa_session_t *sess = pw->fa_sessions_pool + head_session_index;
3419  vlib_cli_output (vm, " last active time: %lu",
3420  sess->last_active_time);
3421  vlib_cli_output (vm, " link enqueue time: %lu",
3422  sess->link_enqueue_time);
3423  }
3424  }
3425 
3426  vlib_cli_output (vm, " Next expiry time: %lu", pw->next_expiry_time);
3427  vlib_cli_output (vm, " Requeue until time: %lu",
3428  pw->requeue_until_time);
3429  vlib_cli_output (vm, " Current time wait interval: %lu",
3431  vlib_cli_output (vm, " Count of deleted sessions: %lu",
3432  pw->cnt_deleted_sessions);
3433  vlib_cli_output (vm, " Delete already deleted: %lu",
3435  vlib_cli_output (vm, " Session timers restarted: %lu",
3437  vlib_cli_output (vm, " Swipe until this time: %lu",
3438  pw->swipe_end_time);
3439  vlib_cli_output (vm, " sw_if_index serviced bitmap: %U",
3440  format_bitmap_hex, pw->serviced_sw_if_index_bitmap);
3441  vlib_cli_output (vm, " pending clear intfc bitmap : %U",
3442  format_bitmap_hex,
3444  vlib_cli_output (vm, " clear in progress: %u", pw->clear_in_process);
3445  vlib_cli_output (vm, " interrupt is pending: %d",
3446  pw->interrupt_is_pending);
3447  vlib_cli_output (vm, " interrupt is needed: %d",
3448  pw->interrupt_is_needed);
3449  vlib_cli_output (vm, " interrupt is unwanted: %d",
3450  pw->interrupt_is_unwanted);
3451  vlib_cli_output (vm, " interrupt generation: %d",
3452  pw->interrupt_generation);
3453  vlib_cli_output (vm, " received session change requests: %d",
3455  vlib_cli_output (vm, " sent session change requests: %d",
3457  }
3458  vlib_cli_output (vm, "\n\nConn cleaner thread counters:");
3459 #define _(cnt, desc) vlib_cli_output(vm, " %20lu: %s", am->cnt, desc);
3461 #undef _
3462  vlib_cli_output (vm, "Interrupt generation: %d",
3464  vlib_cli_output (vm,
3465  "Sessions per interval: min %lu max %lu increment: %f ms current: %f ms",
3468  am->fa_cleaner_wait_time_increment * 1000.0,
3470  1000.0 / (f64) vm->clib_time.clocks_per_second);
3471  vlib_cli_output (vm, "Reclassify sessions: %d", am->reclassify_sessions);
3472 }
3473 
3474 static clib_error_t *
3476  unformat_input_t * input,
3477  vlib_cli_command_t * cmd)
3478 {
3479  clib_error_t *error = 0;
3480  acl_main_t *am = &acl_main;
3481 
3482  u32 show_bihash_verbose = 0;
3483  u32 show_session_thread_id = ~0;
3484  u32 show_session_session_index = ~0;
3485  (void) unformat (input, "thread %u index %u", &show_session_thread_id,
3486  &show_session_session_index);
3487  (void) unformat (input, "verbose %u", &show_bihash_verbose);
3488 
3489  acl_plugin_show_sessions (am, show_session_thread_id,
3490  show_session_session_index);
3491  show_fa_sessions_hash (vm, show_bihash_verbose);
3492  return error;
3493 }
3494 
3495 static clib_error_t *
3497  unformat_input_t * input,
3498  vlib_cli_command_t * cmd)
3499 {
3500  clib_error_t *error = 0;
3501 
3502  u32 acl_index = ~0;
3503  u32 lc_index = ~0;
3504  int show_acl_hash_info = 0;
3505  int show_applied_info = 0;
3506  int show_mask_type = 0;
3507  int show_bihash = 0;
3508  u32 show_bihash_verbose = 0;
3509 
3510  if (unformat (input, "acl"))
3511  {
3512  show_acl_hash_info = 1;
3513  /* mask-type is handy to see as well right there */
3514  show_mask_type = 1;
3515  unformat (input, "index %u", &acl_index);
3516  }
3517  else if (unformat (input, "applied"))
3518  {
3519  show_applied_info = 1;
3520  unformat (input, "lc_index %u", &lc_index);
3521  }
3522  else if (unformat (input, "mask"))
3523  {
3524  show_mask_type = 1;
3525  }
3526  else if (unformat (input, "hash"))
3527  {
3528  show_bihash = 1;
3529  unformat (input, "verbose %u", &show_bihash_verbose);
3530  }
3531 
3532  if (!
3533  (show_mask_type || show_acl_hash_info || show_applied_info
3534  || show_bihash))
3535  {
3536  /* if no qualifiers specified, show all */
3537  show_mask_type = 1;
3538  show_acl_hash_info = 1;
3539  show_applied_info = 1;
3540  show_bihash = 1;
3541  }
3542  vlib_cli_output (vm, "Stats counters enabled for interface ACLs: %d",
3544  if (show_mask_type)
3546  if (show_acl_hash_info)
3548  if (show_applied_info)
3550  if (show_bihash)
3551  acl_plugin_show_tables_bihash (show_bihash_verbose);
3552 
3553  return error;
3554 }
3555 
3556 static clib_error_t *
3558  unformat_input_t * input, vlib_cli_command_t * cmd)
3559 {
3560  clib_error_t *error = 0;
3561  acl_main_t *am = &acl_main;
3564  return error;
3565 }
3566 
3567  /* *INDENT-OFF* */
3568 VLIB_CLI_COMMAND (aclplugin_set_command, static) = {
3569  .path = "set acl-plugin",
3570  .short_help = "set acl-plugin session timeout {{udp idle}|tcp {idle|transient}} <seconds>",
3571  .function = acl_set_aclplugin_fn,
3572 };
3573 
3574 VLIB_CLI_COMMAND (aclplugin_show_acl_command, static) = {
3575  .path = "show acl-plugin acl",
3576  .short_help = "show acl-plugin acl [index N]",
3577  .function = acl_show_aclplugin_acl_fn,
3578 };
3579 
3580 VLIB_CLI_COMMAND (aclplugin_show_lookup_context_command, static) = {
3581  .path = "show acl-plugin lookup context",
3582  .short_help = "show acl-plugin lookup context [index N]",
3584 };
3585 
3586 VLIB_CLI_COMMAND (aclplugin_show_lookup_user_command, static) = {
3587  .path = "show acl-plugin lookup user",
3588  .short_help = "show acl-plugin lookup user [index N]",
3590 };
3591 
3592 VLIB_CLI_COMMAND (aclplugin_show_decode_5tuple_command, static) = {
3593  .path = "show acl-plugin decode 5tuple",
3594  .short_help = "show acl-plugin decode 5tuple XXXX XXXX XXXX XXXX XXXX XXXX",
3596 };
3597 
3598 VLIB_CLI_COMMAND (aclplugin_show_interface_command, static) = {
3599  .path = "show acl-plugin interface",
3600  .short_help = "show acl-plugin interface [sw_if_index N] [acl]",
3601  .function = acl_show_aclplugin_interface_fn,
3602 };
3603 
3604 VLIB_CLI_COMMAND (aclplugin_show_memory_command, static) = {
3605  .path = "show acl-plugin memory",
3606  .short_help = "show acl-plugin memory",
3607  .function = acl_show_aclplugin_memory_fn,
3608 };
3609 
3610 VLIB_CLI_COMMAND (aclplugin_show_sessions_command, static) = {
3611  .path = "show acl-plugin sessions",
3612  .short_help = "show acl-plugin sessions",
3613  .function = acl_show_aclplugin_sessions_fn,
3614 };
3615 
3616 VLIB_CLI_COMMAND (aclplugin_show_tables_command, static) = {
3617  .path = "show acl-plugin tables",
3618  .short_help = "show acl-plugin tables [ acl [index N] | applied [ lc_index N ] | mask | hash [verbose N] ]",
3619  .function = acl_show_aclplugin_tables_fn,
3620 };
3621 
3622 VLIB_CLI_COMMAND (aclplugin_show_macip_acl_command, static) = {
3623  .path = "show acl-plugin macip acl",
3624  .short_help = "show acl-plugin macip acl [index N]",
3625  .function = acl_show_aclplugin_macip_acl_fn,
3626 };
3627 
3628 VLIB_CLI_COMMAND (aclplugin_show_macip_interface_command, static) = {
3629  .path = "show acl-plugin macip interface",
3630  .short_help = "show acl-plugin macip interface",
3632 };
3633 
3634 VLIB_CLI_COMMAND (aclplugin_clear_command, static) = {
3635  .path = "clear acl-plugin sessions",
3636  .short_help = "clear acl-plugin sessions",
3637  .function = acl_clear_aclplugin_fn,
3638 };
3639 
3640 /*?
3641  * [un]Apply an ACL to an interface.
3642  * The ACL is applied in a given direction, either input or output.
3643  * The ACL being applied must already exist.
3644  *
3645  * @cliexpar
3646  * <b><em> set acl-plugin interface <input|output> acl <index> [del] </b></em>
3647  * @cliexend
3648  ?*/
3649 VLIB_CLI_COMMAND (aclplugin_set_interface_command, static) = {
3650  .path = "set acl-plugin interface",
3651  .short_help = "set acl-plugin interface <interface> <input|output> <acl INDEX> [del] ",
3652  .function = acl_set_aclplugin_interface_fn,
3653 };
3654 
3655 /*?
3656  * Create an Access Control List (ACL)
3657  * an ACL is composed of more than one Access control element (ACE). Multiple
3658  * ACEs can be specified with this command using a comma separated list.
3659  *
3660  * Each ACE describes a tuple of src+dst IP prefix, ip protocol, src+dst port ranges.
3661  * (the ACL plugin also support ICMP types/codes instead of UDP/TCP ports, but
3662  * this CLI does not).
3663  *
3664  * An ACL can optionally be assigned a 'tag' - which is an identifier understood
3665  * by the client. VPP does not examine it in any way.
3666  *
3667  * @cliexpar
3668  * <b><em> set acl-plugin acl <permit|deny> src <PREFIX> dst <PREFIX> proto <TCP|UDP> sport <X-Y> dport <X-Y> [tag FOO] </b></em>
3669  * @cliexend
3670  ?*/
3671 VLIB_CLI_COMMAND (aclplugin_set_acl_command, static) = {
3672  .path = "set acl-plugin acl",
3673  .short_help = "set acl-plugin acl <permit|deny> src <PREFIX> dst <PREFIX> proto X sport X-Y dport X-Y [tag FOO] {use comma separated list for multiple rules}",
3674  .function = acl_set_aclplugin_acl_fn,
3675 };
3676 /* *INDENT-ON* */
3677 
3678 static clib_error_t *
3680 {
3681  acl_main_t *am = &acl_main;
3682  u32 conn_table_hash_buckets;
3683  uword conn_table_hash_memory_size;
3684  u32 conn_table_max_entries;
3685  uword main_heap_size;
3686  uword hash_heap_size;
3687  u32 hash_lookup_hash_buckets;
3688  uword hash_lookup_hash_memory;
3689  u32 reclassify_sessions;
3690  u32 use_tuple_merge;
3691  u32 tuple_merge_split_threshold;
3692 
3693  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3694  {
3695  if (unformat
3696  (input, "connection hash buckets %d", &conn_table_hash_buckets))
3697  am->fa_conn_table_hash_num_buckets = conn_table_hash_buckets;
3698  else
3699  if (unformat
3700  (input, "connection hash memory %U", unformat_memory_size,
3701  &conn_table_hash_memory_size))
3702  am->fa_conn_table_hash_memory_size = conn_table_hash_memory_size;
3703  else if (unformat (input, "connection count max %d",
3704  &conn_table_max_entries))
3705  am->fa_conn_table_max_entries = conn_table_max_entries;
3706  else
3707  if (unformat
3708  (input, "main heap size %U", unformat_memory_size,
3709  &main_heap_size))
3710  am->acl_mheap_size = main_heap_size;
3711  else
3712  if (unformat
3713  (input, "hash lookup heap size %U", unformat_memory_size,
3714  &hash_heap_size))
3715  am->hash_lookup_mheap_size = hash_heap_size;
3716  else if (unformat (input, "hash lookup hash buckets %d",
3717  &hash_lookup_hash_buckets))
3718  am->hash_lookup_hash_buckets = hash_lookup_hash_buckets;
3719  else
3720  if (unformat
3721  (input, "hash lookup hash memory %U", unformat_memory_size,
3722  &hash_lookup_hash_memory))
3723  am->hash_lookup_hash_memory = hash_lookup_hash_memory;
3724  else if (unformat (input, "use tuple merge %d", &use_tuple_merge))
3725  am->use_tuple_merge = use_tuple_merge;
3726  else
3727  if (unformat
3728  (input, "tuple merge split threshold %d",
3729  &tuple_merge_split_threshold))
3730  am->tuple_merge_split_threshold = tuple_merge_split_threshold;
3731 
3732  else if (unformat (input, "reclassify sessions %d",
3733  &reclassify_sessions))
3734  am->reclassify_sessions = reclassify_sessions;
3735 
3736  else
3737  return clib_error_return (0, "unknown input '%U'",
3738  format_unformat_error, input);
3739  }
3740  return 0;
3741 }
3742 
3743 VLIB_CONFIG_FUNCTION (acl_plugin_config, "acl-plugin");
3744 
3745 /* Set up the API message handling tables */
3746 #include <vnet/format_fns.h>
3747 #include <acl/acl.api.c>
3748 
3749 static clib_error_t *
3751 {
3752  acl_main_t *am = &acl_main;
3753  clib_error_t *error = 0;
3754  clib_memset (am, 0, sizeof (*am));
3755  am->vlib_main = vm;
3756  am->vnet_main = vnet_get_main ();
3757  am->log_default = vlib_log_register_class ("acl_plugin", 0);
3758 
3759  /* Ask for a correctly-sized block of API message decode slots */
3761 
3762  error = acl_plugin_exports_init (&acl_plugin);
3763 
3764  if (error)
3765  return error;
3766 
3767  am->acl_mheap_size = 0; /* auto size when initializing */
3769 
3772 
3779 
3785  am->reclassify_sessions = 0;
3787 
3794 
3795  vec_validate (am->per_worker_data, tm->n_vlib_mains - 1);
3796  {
3797  u16 wk;
3798  for (wk = 0; wk < vec_len (am->per_worker_data); wk++)
3799  {
3801  if (tm->n_vlib_mains > 1)
3802  {
3804  }
3805  vec_validate (pw->expired,
3806  ACL_N_TIMEOUTS *
3808  _vec_len (pw->expired) = 0;
3814  ACL_N_TIMEOUTS - 1, ~0ULL);
3815  }
3816  }
3817 
3818  am->fa_cleaner_cnt_delete_by_sw_index = 0;
3819  am->fa_cleaner_cnt_delete_by_sw_index_ok = 0;
3820  am->fa_cleaner_cnt_unknown_event = 0;
3821  am->fa_cleaner_cnt_timer_restarted = 0;
3822  am->fa_cleaner_cnt_wait_with_timeout = 0;
3823 
3824 
3825 #define _(N, v, s) am->fa_ipv6_known_eh_bitmap = clib_bitmap_set(am->fa_ipv6_known_eh_bitmap, v, 1);
3827 #undef _
3829 
3830  /* use the new fancy hash-based matching */
3831  am->use_hash_acl_matching = 1;
3832  /* use tuplemerge by default */
3833  am->use_tuple_merge = 1;
3834  /* Set the default threshold */
3836 
3837  am->interface_acl_user_id =
3838  acl_plugin.register_user_module ("interface ACL", "sw_if_index",
3839  "is_input");
3840 
3843  am->acl_counter_lock[0] = 0; /* should be no need */
3844 
3845  return error;
3846 }
3847 
3849 
3850 
3851 /*
3852  * fd.io coding-style-patch-verification: ON
3853  *
3854  * Local Variables:
3855  * eval: (c-set-style "gnu")
3856  * End:
3857  */
static void vl_api_acl_stats_intf_counters_enable_t_handler(vl_api_acl_stats_intf_counters_enable_t *mp)
Definition: acl.c:1898
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:209
acl_rule_t * rules
Definition: acl.h:84
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
u32 * input_policy_epoch_by_sw_if_index
Definition: acl.h:173
static int acl_api_invalid_prefix(const vl_api_prefix_t *prefix)
Definition: acl.c:347
u8 * format_vec16(u8 *s, va_list *va)
Definition: acl.c:66
macip_acl_rule_t * rules
Definition: acl.h:93
u8 count
Definition: dhcp.api:208
static int macip_acl_interface_add_acl(acl_main_t *am, u32 sw_if_index, u32 macip_acl_index)
Definition: acl.c:1739
u8 src_mac[6]
Definition: acl.h:70
u32 fa_cleaner_node_index
Definition: acl.h:234
u32 session_timeout_sec[ACL_N_TIMEOUTS]
Definition: acl.h:236
static clib_error_t * acl_set_aclplugin_interface_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:2854
Use acl_interface_set_acl_list instead Append/remove an ACL index to/from the list of ACLs checked fo...
Definition: acl.api:154
#define vec_foreach_index(var, v)
Iterate over vector indices.
static int macip_acl_interface_add_del_acl(u32 sw_if_index, u8 is_add, u32 acl_list_index)
Definition: acl.c:1807
static void vl_api_acl_plugin_get_conn_table_max_entries_t_handler(vl_api_acl_plugin_get_conn_table_max_entries_t *mp)
Definition: acl.c:240
static clib_error_t * acl_clear_aclplugin_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:3557
static int acl_set_skip_ipv6_eh(u32 eh, u32 value)
Definition: acl.c:2557
vl_api_prefix_t dst_prefix
Definition: acl_types.api:45
static clib_error_t * acl_show_aclplugin_lookup_user_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:3163
static int verify_message_len(void *mp, u32 expected_len, char *where)
Definition: acl.c:1840
#define UDP_SESSION_IDLE_TIMEOUT_SEC
Definition: acl.h:40
static clib_error_t * acl_init(vlib_main_t *vm)
Definition: acl.c:3750
u32 acl_index
Definition: abf.api:60
u8 is_ipv6
Definition: types.h:24
#define FA_SESSION_BOGUS_INDEX
Definition: fa_node.h:166
uword * pending_clear_sw_if_index_bitmap
Definition: fa_node.h:206
static void acl_plugin_counter_lock(acl_main_t *am)
Definition: acl.h:325
void acl_plugin_show_tables_mask_type(void)
Definition: hash_lookup.c:1203
vlib_combined_counter_main_t * combined_acl_counters
Definition: acl.h:309
void vlib_validate_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
validate a combined counter
Definition: counter.c:108
static void vl_api_acl_plugin_get_version_t_handler(vl_api_acl_plugin_get_version_t *mp)
Definition: acl.c:141
a
Definition: bitmap.h:538
u64 fa_current_cleaner_timer_wait_interval
Definition: acl.h:276
Set the vector of input/output ACLs checked for an interface.
Definition: acl.api:178
char * stat_segment_name
Name in stat segment directory.
Definition: counter.h:194
vl_api_interface_index_t sw_if_index
Definition: acl.api:418
Set the ethertype whitelists on an interface.
Definition: acl.api:445
u32 ** input_acl_vec_by_sw_if_index
Definition: acl.h:158
u16 msg_id_base
Definition: acl.h:123
#define ntohs(x)
Definition: af_xdp.bpf.c:29
void acl_plugin_hash_acl_set_trace_heap(int on)
Definition: hash_lookup.c:622
void acl_plugin_show_tables_applied_info(u32 lc_index)
Definition: hash_lookup.c:1281
Dump the list(s) of ACL applied to specific or all interfaces.
Definition: acl.api:231
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
vl_api_macip_acl_rule_t r[count]
Definition: acl.api:270
bool is_add[default=true]
Definition: acl.api:346
u32 out_l2_table_index
Definition: acl.h:101
void mac_address_encode(const mac_address_t *in, u8 *out)
static int count_skip(u8 *p, u32 size)
Definition: acl.c:507
vnet_interface_main_t interface_main
Definition: vnet.h:59
static void vl_api_acl_add_replace_t_handler(vl_api_acl_add_replace_t *mp)
Definition: acl.c:1857
static void vl_api_macip_acl_dump_t_handler(vl_api_macip_acl_dump_t *mp)
Definition: acl.c:2287
#define clib_error(format, args...)
Definition: error.h:62
unsigned long u64
Definition: types.h:89
int l4_match_nonfirst_fragment
Definition: acl.h:247
Control ping from the client to the server response.
Definition: acl.api:67
#define ACL_FA_CONN_TABLE_DEFAULT_HASH_NUM_BUCKETS
Definition: fa_node.h:23
#define ACL_PLUGIN_VERSION_MINOR
Definition: acl.h:38
static clib_error_t * acl_plugin_config(vlib_main_t *vm, unformat_input_t *input)
Definition: acl.c:3679
#define ACL_PLUGIN_HASH_LOOKUP_HASH_MEMORY
Definition: acl.h:48
#define REPLY_MACRO2(t, body)
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static void vl_api_macip_acl_add_t_handler(vl_api_macip_acl_add_t *mp)
Definition: acl.c:2154
static void vl_api_acl_interface_etype_whitelist_dump_t_handler(vl_api_acl_interface_list_dump_t *mp)
Definition: acl.c:2499
Details about ethertype whitelist on a single interface.
Definition: acl.api:478
f64 clocks_per_second
Definition: time.h:54
u8 dst_prefixlen
Definition: types.h:28
static void vl_api_send_msg(vl_api_registration_t *rp, u8 *elem)
Definition: api.h:35
vl_api_interface_index_t sw_if_index
Definition: acl.api:481
fa_5tuple_t info
Definition: fa_node.h:106
Reply to get connection table max entries.
Definition: acl.api:90
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
static u64 clib_cpu_time_now(void)
Definition: time.h:81
u32 l2_table_index
Definition: acl.h:97
vl_api_address_t src
Definition: gre.api:54
static void acl_clear_sessions(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:560
static int get_l3_dst_offset(int is6)
Definition: acl.c:1016
u16 srcport_or_icmptype_last
Definition: acl_types.api:61
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
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
u64 session_timeout[ACL_N_TIMEOUTS]
Definition: acl.h:284
fa_session_t * fa_sessions_pool
Definition: fa_node.h:170
u16 srcport_or_icmptype_first
Definition: acl_types.api:60
vlib_main_t * vm
Definition: in2out_ed.c:1582
bool is_add[default=true]
Definition: acl.api:158
u32 * output_policy_epoch_by_sw_if_index
Definition: acl.h:174
u32 out_dot1q_table_index
Definition: acl.c:947
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
void(* acl_vector_print_func_t)(vlib_main_t *vm, u8 *out0)
Definition: acl.c:193
unformat_function_t unformat_vnet_sw_interface
clib_time_t clib_time
Definition: main.h:124
u32 dot1ad_table_index
Definition: acl.c:941
u8 link_list_id
Definition: fa_node.h:117
static void validate_and_reset_acl_counters(acl_main_t *am, u32 acl_index)
Definition: acl.c:314
vl_api_prefix_t prefix
Definition: ip.api:144
u16 mask
Definition: flow_types.api:52
void * vl_msg_api_alloc(int nbytes)
Delete a MACIP ACL.
Definition: acl.api:326
unsigned char u8
Definition: types.h:56
#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:954
vl_api_interface_index_t sw_if_index
Definition: acl.api:164
u32 table_index
Definition: acl.c:938
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
vlib_log_class_t log_default
Definition: acl.h:306
double f64
Definition: types.h:142
Details about one MACIP ACL.
Definition: acl.api:375
void acl_plugin_lookup_context_notify_acl_change(u32 acl_num)
f64 fa_cleaner_wait_time_increment
Definition: acl.h:274
u32 arp_dot1q_table_index
Definition: acl.c:942
#define clib_bitmap_validate(v, n_bits)
Definition: bitmap.h:115
u32 interface_acl_user_id
Definition: acl.h:153
u32 ** lc_index_vec_by_acl
Definition: acl.h:170
uword fa_conn_table_hash_memory_size
Definition: acl.h:251
u16 dst_port_or_code_last
Definition: types.h:33
static int acl_interface_in_enable_disable(acl_main_t *am, u32 sw_if_index, int enable_disable)
Definition: acl.c:571
static clib_error_t * acl_sw_interface_add_del(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
Definition: acl.c:2573
u8 src_mac_mask[6]
Definition: acl.h:71
u8 src_prefixlen
Definition: types.h:26
ip46_address_t src_ip_addr
Definition: acl.h:72
void mv(vnet_classify_table_t *t)
Definition: vnet_classify.c:76
void vlib_clear_combined_counters(vlib_combined_counter_main_t *cm)
Clear a collection of combined counters.
Definition: counter.c:61
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:513
u32 link_prev_idx
Definition: fa_node.h:115
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
static int acl_is_not_defined(acl_main_t *am, u32 acl_list_index)
Definition: acl.c:673
static clib_error_t * acl_show_aclplugin_acl_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:3135
volatile u32 * acl_counter_lock
Definition: acl.h:308
u64 fa_conn_table_max_entries
Definition: acl.h:252
static uword clib_bitmap_is_zero(uword *ai)
predicate function; is an entire bitmap empty?
Definition: bitmap.h:57
static int acl_is_used_by(u32 acl_index, u32 **foo_index_vec_by_acl)
Definition: acl.c:463
vnet_main_t * vnet_main
Definition: acl.h:304
ip46_address_t src
Definition: types.h:25
u8 * format_memory_size(u8 *s, va_list *va)
Definition: std-formats.c:209
#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:342
static void increment_policy_epoch(acl_main_t *am, u32 sw_if_index, int is_input)
Definition: acl.c:275
static clib_error_t * acl_show_aclplugin_interface_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:3281
#define clib_error_return(e, args...)
Definition: error.h:99
static u8 * format_acl_action(u8 *s, u8 action)
Definition: manual_fns.h:110
u8 src_prefixlen
Definition: acl.h:73
u8 is_permit
Definition: types.h:23
#define ACL_FA_CONN_TABLE_DEFAULT_MAX_ENTRIES
Definition: fa_node.h:25
uword * in_acl_on_sw_if_index
Definition: acl.h:166
static void acl_print_acl(vlib_main_t *vm, acl_main_t *am, int acl_index)
Definition: acl.c:263
u32 acl_index[default=0xffffffff]
Definition: acl.api:300
u8 mac_mask[6]
Definition: acl.c:935
u32 out_arp_dot1q_table_index
Definition: acl.c:949
unsigned int u32
Definition: types.h:88
#define vec_search(v, E)
Search a vector for the index of the entry that matches.
Definition: vec.h:1012
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(acl_sw_interface_add_del)
static clib_error_t * acl_show_aclplugin_decode_5tuple_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:3262
u32 ip4_table_index
Definition: acl.h:95
Get Connection table max entries.
Definition: acl.api:80
ip46_type_t ip_address_decode(const vl_api_address_t *in, ip46_address_t *out)
Decode/Encode for struct/union types.
Definition: ip_types_api.c:160
Reply to add/replace MACIP ACL.
Definition: acl.api:313
static u8 * my_macip_acl_rule_t_pretty_format(u8 *out, va_list *args)
Definition: acl.c:2808
ip46_address_t dst
Definition: types.h:27
unformat_function_t unformat_line_input
Definition: format.h:283
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:63
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)
u8 * format_mheap(u8 *s, va_list *va)
Definition: mem_dlmalloc.c:404
vnet_crypto_main_t * cm
Definition: quic_crypto.c:53
static clib_error_t * acl_show_aclplugin_memory_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:3298
Reply to add MACIP ACL.
Definition: acl.api:280
#define clib_bitmap_foreach(i, ai, body)
Macro to iterate across set bits in a bitmap.
Definition: bitmap.h:361
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
static void acl_plugin_show_interface(acl_main_t *am, u32 sw_if_index, int show_acl, int detail)
Definition: acl.c:3178
Details about a single MACIP ACL contents.
Definition: acl.api:428
static void acl_set_session_max_entries(u32 value)
Definition: acl.c:2550
Control ping from client to api server request.
Definition: acl.api:55
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:1015
VLIB_PLUGIN_REGISTER()
#define ACL_FA_DEFAULT_CLEANER_WAIT_TIME_INCREMENT
Definition: acl.h:273
u16 dst_port_or_code_first
Definition: types.h:32
vl_api_ip_proto_t proto
Definition: acl_types.api:50
#define TCP_SESSION_IDLE_TIMEOUT_SEC
Definition: acl.h:41
static void warning_acl_print_acl(vlib_main_t *vm, acl_main_t *am, int acl_index)
Definition: acl.c:269
string tag[64]
Definition: acl.api:220
static void vl_api_acl_dump_t_handler(vl_api_acl_dump_t *mp)
Definition: acl.c:2033
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
uword * fa_ipv6_known_eh_bitmap
Definition: acl.h:244
u64 memory_size
Definition: vhost_user.h:105
Replace an existing ACL in-place or create a new ACL.
Definition: acl.api:105
#define ACL_FA_DEFAULT_MIN_DELETED_SESSIONS_PER_INTERVAL
Definition: acl.h:270
u32 size
Definition: vhost_user.h:106
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:302
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:429
u32 * output_lc_index_by_sw_if_index
Definition: acl.h:151
void acl_plugin_acl_set_validate_heap(acl_main_t *am, int on)
Definition: acl.c:129
Details about a single ACL contents.
Definition: acl.api:247
static clib_error_t * acl_show_aclplugin_tables_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:3496
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:182
#define REPLY_MACRO(t)
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:875
vl_api_acl_rule_t r[count]
Definition: acl.api:112
static void send_acl_details(acl_main_t *am, vl_api_registration_t *reg, acl_list_t *acl, u32 context)
Definition: acl.c:2001
vl_api_address_union_t src_address
Definition: ip_types.api:111
static int get_l3_src_offset(int is6)
Definition: acl.c:1005
f64 seconds_per_clock
Definition: time.h:58
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: in_out_acl.c:129
u64 last_active_time
Definition: fa_node.h:107
static int macip_maybe_apply_unapply_classifier_tables(acl_main_t *am, u32 acl_index, int is_apply)
Definition: acl.c:1587
static void send_acl_interface_etype_whitelist_details(acl_main_t *am, vl_api_registration_t *reg, u32 sw_if_index, u32 context)
Definition: acl.c:2440
vl_api_address_t dst
Definition: gre.api:55
u32 interface_acl_counters_enabled
Definition: acl.h:311
void acl_plugin_hash_acl_set_validate_heap(int on)
Definition: hash_lookup.c:615
u8 proto
Definition: types.h:29
static u8 * my_format_mac_address(u8 *s, va_list *args)
Definition: acl.c:2800
u64 * fa_conn_list_head_expiry_time
Definition: fa_node.h:181
u32 out_arp_dot1ad_table_index
Definition: acl.c:950
#define FA_POLICY_EPOCH_IS_INPUT
Definition: fa_node.h:126
u16 src_port_or_type_first
Definition: types.h:30
u64 fa_min_deleted_sessions_per_interval
Definition: acl.h:271
static int match_type_compare(macip_match_type_t *m1, macip_match_type_t *m2)
Definition: acl.c:997
static void acl_print_acl_x(acl_vector_print_func_t vpr, vlib_main_t *vm, acl_main_t *am, int acl_index)
Definition: acl.c:196
format_function_t format_ip46_address
Definition: ip46_address.h:50
void acl_plugin_show_tables_bihash(u32 show_bihash_verbose)
Definition: hash_lookup.c:1331
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P with alignment A.
Definition: pool.h:246
vl_api_prefix_t src_prefix
Definition: acl_types.api:44
union fa_session_t::@16 tcp_flags_seen
vl_api_acl_rule_t r[count]
Definition: acl.api:222
An API client registration, only in vpp/vlib.
Definition: api_common.h:47
Dump the list(s) of MACIP ACLs applied to specific or all interfaces.
Definition: acl.api:414
static void vl_api_acl_interface_set_etype_whitelist_t_handler(vl_api_acl_interface_set_etype_whitelist_t *mp)
Definition: acl.c:2410
int vnet_l2_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
static int match_type_metric(macip_match_type_t *m)
Definition: acl.c:976
static int macip_acl_del_list(u32 acl_list_index)
Definition: acl.c:1771
Dump one or all defined MACIP ACLs.
Definition: acl.api:359
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
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:522
int ip_prefix_decode2(const vl_api_prefix_t *in, ip_prefix_t *out)
Definition: ip_types_api.c:250
static void acl_plugin_show_acl(acl_main_t *am, u32 acl_index)
Definition: acl.c:3096
static uword * clib_bitmap_dup_xor(uword *ai, uword *bi)
Logical operator across two bitmaps which duplicates the first bitmap.
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
u64 fa_session_total_adds
Definition: acl.h:238
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
void acl_plugin_acl_set_trace_heap(acl_main_t *am, int on)
Definition: acl.c:135
void * heap_base
Definition: main.h:174
u32 dot1q_table_index
Definition: acl.c:940
void acl_fa_enable_disable(u32 sw_if_index, int is_input, int enable_disable)
static int acl_stats_intf_counters_enable_disable(acl_main_t *am, int enable_disable)
Definition: acl.c:653
static void * clib_mem_set_heap(void *heap)
Definition: mem.h:268
Reply to add/replace ACL.
Definition: acl.api:122
#define clib_warning(format, args...)
Definition: error.h:59
Reply with the vector of MACIP ACLs by sw_if_index.
Definition: acl.api:401
static void acl_plugin_counter_unlock(acl_main_t *am)
Definition: acl.h:333
u8 * format_vec32(u8 *s, va_list *va)
Definition: std-formats.c:43
void acl_plugin_show_lookup_user(u32 user_index)
u32 sw_if_index
Definition: fa_node.h:108
int use_hash_acl_matching
Definition: acl.h:185
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:299
static clib_error_t * acl_plugin_exports_init(acl_plugin_methods_t *m)
static uword clib_bitmap_get(uword *ai, uword i)
Gets the ith bit value from a bitmap.
Definition: bitmap.h:197
vl_api_interface_index_t sw_if_index
Definition: acl.api:449
uword hash_lookup_hash_memory
Definition: acl.h:134
static vl_api_registration_t * vl_api_client_index_to_registration(u32 index)
Definition: api.h:79
#define foreach_fa_cleaner_counter
Definition: acl.h:289
vl_api_macip_acl_rule_t r[count]
Definition: acl.api:303
u32 acl_index[default=0xffffffff]
Definition: acl.api:363
static int acl_interface_out_enable_disable(acl_main_t *am, u32 sw_if_index, int enable_disable)
Definition: acl.c:611
int tuple_merge_split_threshold
Definition: acl.h:192
vl_api_interface_index_t sw_if_index
Definition: acl.api:348
vl_api_mac_address_t src_mac
Definition: acl_types.api:93
u8 is_ipv6
Definition: acl.h:69
u32 out_arp_table_index
Definition: acl.c:946
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:55
vl_api_gbp_rule_t rules[n_rules]
Definition: gbp.api:338
int trace_acl
Definition: acl.h:255
static clib_error_t * acl_show_aclplugin_macip_acl_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:3044
#define ACL_PLUGIN_HASH_LOOKUP_HASH_BUCKETS
Definition: acl.h:47
signed int i32
Definition: types.h:77
u32 hash_lookup_hash_buckets
Definition: acl.h:133
vl_api_interface_index_t sw_if_index
Definition: acl.api:431
static void vl_api_acl_interface_add_del_t_handler(vl_api_acl_interface_add_del_t *mp)
Definition: acl.c:1911
u8 value
Definition: qos.api:54
#define ASSERT(truth)
static int macip_acl_interface_del_acl(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:1702
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
int trace_sessions
Definition: acl.h:254
u32 out_ip6_table_index
Definition: acl.h:100
u8 tag[64]
Definition: acl.h:83
static void vl_api_macip_acl_del_t_handler(vl_api_macip_acl_del_t *mp)
Definition: acl.c:2208
#define vec_validate_acl_rules(v, idx)
Definition: acl.c:2898
static int acl_interface_inout_enable_disable(acl_main_t *am, u32 sw_if_index, int is_input, int enable_disable)
Definition: acl.c:663
u16 src_port_or_type_last
Definition: types.h:31
static int macip_create_classify_tables(acl_main_t *am, u32 macip_acl_index)
Definition: acl.c:1039
static void acl_set_timeout_sec(int timeout_type, u32 value)
Definition: acl.c:2531
void * mheap_alloc_with_lock(void *memory, uword size, int locked)
Definition: mem_dlmalloc.c:507
uword * out_acl_on_sw_if_index
Definition: acl.h:167
void acl_plugin_show_lookup_context(u32 lc_index)
u32 ** sw_if_index_vec_by_macip_acl
Definition: acl.h:224
static int macip_permit_also_egress(u8 is_permit)
Definition: acl.c:1033
#define clib_bitmap_free(v)
Free a bitmap.
Definition: bitmap.h:92
acl_main_t acl_main
Definition: acl.c:42
vnet_classify_main_t vnet_classify_main
Definition: vnet_classify.c:29
static void vl_api_macip_acl_add_replace_t_handler(vl_api_macip_acl_add_replace_t *mp)
Definition: acl.c:2181
Delete an ACL.
Definition: acl.api:135
Reply to get the plugin version.
Definition: acl.api:44
static int macip_acl_add_list(u32 count, vl_api_macip_acl_rule_t rules[], u32 *acl_list_index, u8 *tag)
Definition: acl.c:1614
unformat_function_t unformat_ip46_address
Definition: format.h:63
uword * serviced_sw_if_index_bitmap
Definition: fa_node.h:204
u32 count
Definition: acl.h:92
vl_api_macip_acl_rule_t r[count]
Definition: acl.api:381
Reply to set the ACL list on an interface.
Definition: acl.api:200
u32 link_next_idx
Definition: fa_node.h:116
uword acl_mheap_size
Definition: acl.h:120
int vnet_classify_add_del_table(vnet_classify_main_t *cm, u8 *mask, u32 nbuckets, u32 memory_size, u32 skip, u32 match, u32 next_table_index, u32 miss_next_index, u32 *table_index, u8 current_data_flag, i16 current_data_offset, int is_add, int del_chain)
#define vec_elt(v, i)
Get vector value at index i.
static void macip_acl_print(acl_main_t *am, u32 macip_acl_index)
Definition: acl.c:2823
u32 * macip_acl_by_sw_if_index
Definition: acl.h:221
Get the vector of MACIP ACL IDs applied to the interfaces.
Definition: acl.api:389
static void vl_api_acl_interface_list_dump_t_handler(vl_api_acl_interface_list_dump_t *mp)
Definition: acl.c:2120
u16 as_u16
Definition: fa_node.h:111
static void acl_interface_reset_inout_acls(u32 sw_if_index, u8 is_input, int *may_clear_sessions)
Definition: acl.c:821
Add/Replace a MACIP ACL.
Definition: acl.api:296
static int acl_add_list(u32 count, vl_api_acl_rule_t rules[], u32 *acl_list_index, u8 *tag)
Definition: acl.c:354
static void print_clib_warning_and_reset(vlib_main_t *vm, u8 *out0)
Definition: acl.c:180
static int acl_set_etype_whitelists(acl_main_t *am, u32 sw_if_index, u16 *vec_in, u16 *vec_out)
Definition: acl.c:894
u32 out_table_index
Definition: acl.c:945
static clib_error_t * acl_set_aclplugin_acl_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:2909
u32 arp_dot1ad_table_index
Definition: acl.c:943
static void vl_api_acl_del_t_handler(vl_api_acl_del_t *mp)
Definition: acl.c:1884
static void send_macip_acl_details(acl_main_t *am, vl_api_registration_t *reg, macip_acl_list_t *acl, u32 context)
Definition: acl.c:2240
macip_acl_list_t * macip_acls
Definition: acl.h:155
static clib_error_t * acl_show_aclplugin_sessions_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:3475
static acl_plugin_methods_t acl_plugin
Definition: acl.c:62
static void send_macip_acl_interface_list_details(acl_main_t *am, vl_api_registration_t *reg, u32 sw_if_index, u32 acl_index, u32 context)
Definition: acl.c:2349
vl_api_mac_event_action_t action
Definition: l2.api:181
uword hash_lookup_mheap_size
Definition: acl.h:138
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Details about a single ACL contents.
Definition: acl.api:216
u32 ip6_table_index
Definition: acl.h:96
static void vl_api_macip_acl_interface_list_dump_t_handler(vl_api_macip_acl_interface_list_dump_t *mp)
Definition: acl.c:2374
u8 tcp_flags_mask
Definition: types.h:35
vl_api_mac_address_t src_mac_mask
Definition: acl_types.api:94
acl_fa_per_worker_data_t * per_worker_data
Definition: acl.h:281
u64 uword
Definition: types.h:112
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:1055
u16 dstport_or_icmpcode_first
Definition: acl_types.api:62
static void unformat_free(unformat_input_t *i)
Definition: format.h:163
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:872
int fa_interrupt_generation
Definition: acl.h:278
u32 ** input_sw_if_index_vec_by_acl
Definition: acl.h:162
char * name
The counter collection&#39;s name.
Definition: counter.h:193
int use_tuple_merge
Definition: acl.h:188
u16 ** output_etype_whitelist_by_sw_if_index
Definition: acl.h:218
u32 index
Definition: flow_types.api:221
static void vl_api_acl_interface_set_acl_list_t_handler(vl_api_acl_interface_set_acl_list_t *mp)
Definition: acl.c:1931
u64 fa_max_deleted_sessions_per_interval
Definition: acl.h:263
void * acl_mheap
Definition: acl.h:119
void * acl_plugin_set_heap()
Definition: acl.c:122
static clib_error_t * acl_set_aclplugin_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:2600
vl_api_interface_index_t sw_if_index[default=0xffffffff]
Definition: acl.api:235
vl_api_interface_index_t sw_if_index
Definition: acl.api:182
u16 thread_index
Definition: fa_node.h:112
void ip_address_encode(const ip46_address_t *in, ip46_type_t type, vl_api_address_t *out)
Definition: ip_types_api.c:194
unformat_function_t unformat_memory_size
Definition: format.h:296
static void try_increment_acl_policy_epoch(acl_main_t *am, u32 acl_num, int is_input)
Definition: acl.c:290
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:165
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:832
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
static void policy_notify_acl_change(acl_main_t *am, u32 acl_num)
Definition: acl.c:306
u8 tcp_flags_value
Definition: types.h:34
Get the plugin version.
Definition: acl.api:32
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
static void acl_plugin_show_sessions(acl_main_t *am, u32 show_session_thread_id, u32 show_session_session_index)
Definition: acl.c:3327
static void copy_acl_rule_to_api_rule(vl_api_acl_rule_t *api_rule, acl_rule_t *r)
Definition: acl.c:1982
u16 ** input_etype_whitelist_by_sw_if_index
Definition: acl.h:217
#define vec_foreach(var, vec)
Vector iterator.
static void * acl_set_heap(acl_main_t *am)
Definition: acl.c:81
static void setup_message_id_table(snat_main_t *sm, api_main_t *am)
Definition: nat_api.c:2804
clib_spinlock_t pending_session_change_request_lock
Definition: fa_node.h:172
unsigned long long u32x4
Definition: ixge.c:28
void * hash_lookup_mheap
Definition: acl.h:137
u64 fa_session_total_deactivations
Definition: acl.h:241
static void print_cli_and_reset(vlib_main_t *vm, u8 *out0)
Definition: acl.c:187
Add a MACIP ACL.
Definition: acl.api:264
bool is_ipv6
Definition: dhcp.api:202
int reclassify_sessions
Definition: acl.h:177
void show_fa_sessions_hash(vlib_main_t *vm, u32 verbose)
u8 * format_acl_plugin_5tuple(u8 *s, va_list *args)
u32 * input_lc_index_by_sw_if_index
Definition: acl.h:150
u32 vl_msg_api_get_msg_length(void *msg_arg)
Definition: api_shared.c:777
Definition: acl.h:79
u32 out_ip4_table_index
Definition: acl.h:99
u32 client_index
Definition: acl.api:202
u16 dstport_or_icmpcode_last
Definition: acl_types.api:63
u32 ** output_sw_if_index_vec_by_acl
Definition: acl.h:163
#define ACL_PLUGIN_VERSION_MAJOR
Definition: acl.h:37
u8 tag[64]
Definition: acl.h:91
static clib_error_t * acl_show_aclplugin_macip_interface_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:3080
#define FA_POLICY_EPOCH_MASK
Definition: fa_node.h:124
#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:556
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
#define ACL_PLUGIN_HASH_LOOKUP_HEAP_SIZE
Definition: acl.h:46
static int intf_has_etype_whitelist(acl_main_t *am, u32 sw_if_index, int is_input)
Definition: acl.c:550
void acl_plugin_show_tables_acl_hash_info(u32 acl_index)
Definition: hash_lookup.c:1222
#define TM_SPLIT_THRESHOLD
Definition: acl.h:191
vl_api_interface_index_t sw_if_index
Definition: acl.api:250
static int acl_interface_set_inout_acl_list(acl_main_t *am, u32 sw_if_index, u8 is_input, u32 *vec_acl_list_index, int *may_clear_sessions)
Definition: acl.c:679
#define ACL_FA_DEFAULT_MAX_DELETED_SESSIONS_PER_INTERVAL
Definition: acl.h:262
static void vl_api_acl_plugin_control_ping_t_handler(vl_api_acl_plugin_control_ping_t *mp)
Definition: acl.c:164
void mac_address_decode(const u8 *in, mac_address_t *out)
Conversion functions to/from (decode/encode) API types to VPP internal types.
acl_list_t * acls
Definition: acl.h:130
int vnet_set_output_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: in_out_acl.c:139
u32 ** output_acl_vec_by_sw_if_index
Definition: acl.h:159
static clib_error_t * acl_show_aclplugin_lookup_context_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:3149
u32 out_dot1ad_table_index
Definition: acl.c:948
#define TCP_SESSION_TRANSIENT_TIMEOUT_SEC
Definition: acl.h:42
u8 is_permit
Definition: acl.h:68
static void vl_api_macip_acl_interface_add_del_t_handler(vl_api_macip_acl_interface_add_del_t *mp)
Definition: acl.c:2221
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:33
u32 arp_table_index
Definition: acl.c:939
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
u64 link_enqueue_time
Definition: fa_node.h:114
string tag[64]
Definition: acl.api:268
u32 fa_conn_table_hash_num_buckets
Definition: acl.h:250
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
#define ACL_FA_CONN_TABLE_DEFAULT_HASH_MEMORY_SIZE
Definition: fa_node.h:24
u64 fa_session_total_dels
Definition: acl.h:239
static int acl_del_list(u32 acl_list_index)
Definition: acl.c:477
static void send_acl_interface_list_details(acl_main_t *am, vl_api_registration_t *reg, u32 sw_if_index, u32 context)
Definition: acl.c:2073
static void macip_destroy_classify_tables(acl_main_t *am, u32 macip_acl_index)
Definition: acl.c:1543
Enable or disable incrementing ACL counters in stats segment by interface processing.
Definition: acl.api:493
static void vl_api_macip_acl_interface_get_t_handler(vl_api_macip_acl_interface_get_t *mp)
Definition: acl.c:2320
foreach_fa_cleaner_counter vlib_main_t * vlib_main
Definition: acl.h:303