FD.io VPP  v20.05-21-gb1500e9ff
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;
419  r->src_port_or_type_last = ntohs (rules[i].srcport_or_icmptype_last);
421  r->dst_port_or_code_last = ntohs (rules[i].dstport_or_icmpcode_last);
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  if (vec_len (vec_acl_list_index) > 0)
786  {
787  u32 lc_index = (*pinout_lc_index_by_sw_if_index)[sw_if_index];
788  if (~0 == lc_index)
789  {
790  lc_index =
791  acl_plugin.get_lookup_context_index (am->interface_acl_user_id,
792  sw_if_index, is_input);
793  (*pinout_lc_index_by_sw_if_index)[sw_if_index] = lc_index;
794  }
795  acl_plugin.set_acl_vec_for_context (lc_index, vec_acl_list_index);
796  }
797  else
798  {
799  if (~0 != (*pinout_lc_index_by_sw_if_index)[sw_if_index])
800  {
801  acl_plugin.put_lookup_context_index ((*pinout_lc_index_by_sw_if_index)[sw_if_index]);
802  (*pinout_lc_index_by_sw_if_index)[sw_if_index] = ~0;
803  }
804  }
805 
806  /* ensure ACL processing is enabled/disabled as needed */
807  acl_interface_inout_enable_disable (am, sw_if_index, is_input,
808  vec_len (vec_acl_list_index) > 0);
809 
810 done:
811  clib_bitmap_free (change_acl_bitmap);
812  clib_bitmap_free (seen_acl_bitmap);
813  clib_bitmap_free (old_seen_acl_bitmap);
814  return rv;
815 }
816 
817 static void
819  int *may_clear_sessions)
820 {
821  acl_main_t *am = &acl_main;
822  void *oldheap = acl_set_heap (am);
823  acl_interface_set_inout_acl_list (am, sw_if_index, is_input, 0,
824  may_clear_sessions);
825  clib_mem_set_heap (oldheap);
826 }
827 
828 static int
830  u32 acl_list_index)
831 {
832 
833  acl_main_t *am = &acl_main;
834  u32 *acl_vec = 0;
835  int may_clear_sessions = 1;
836 
837  int error_already_applied = is_input ? VNET_API_ERROR_ACL_IN_USE_INBOUND
838  : VNET_API_ERROR_ACL_IN_USE_OUTBOUND;
839 
840  u32 ***pinout_acl_vec_by_sw_if_index =
841  is_input ? &am->
842  input_acl_vec_by_sw_if_index : &am->output_acl_vec_by_sw_if_index;
843  int rv = 0;
844  void *oldheap = acl_set_heap (am);
845 
846  if (is_add)
847  {
848  vec_validate ((*pinout_acl_vec_by_sw_if_index), sw_if_index);
849  u32 index = vec_search ((*pinout_acl_vec_by_sw_if_index)[sw_if_index],
850  acl_list_index);
851 
852  if (~0 != index)
853  {
854  rv = error_already_applied;
855  goto done;
856  }
857 
858  acl_vec = vec_dup ((*pinout_acl_vec_by_sw_if_index)[sw_if_index]);
859  vec_add1 (acl_vec, acl_list_index);
860  }
861  else
862  {
863  if (sw_if_index >= vec_len (*pinout_acl_vec_by_sw_if_index))
864  {
865  rv = VNET_API_ERROR_NO_SUCH_ENTRY;
866  goto done;
867  }
868 
869  u32 index = vec_search ((*pinout_acl_vec_by_sw_if_index)[sw_if_index],
870  acl_list_index);
871 
872  if (~0 == index)
873  {
874  rv = VNET_API_ERROR_NO_SUCH_ENTRY;
875  goto done;
876  }
877 
878  acl_vec = vec_dup ((*pinout_acl_vec_by_sw_if_index)[sw_if_index]);
879  vec_del1 (acl_vec, index);
880  }
881 
882  rv = acl_interface_set_inout_acl_list (am, sw_if_index, is_input, acl_vec,
883  &may_clear_sessions);
884 done:
885  vec_free (acl_vec);
886  clib_mem_set_heap (oldheap);
887  return rv;
888 }
889 
890 static int
892  u16 * vec_out)
893 {
896 
899 
902 
903  /*
904  * if there are already inbound/outbound ACLs applied, toggle the
905  * enable/disable - this will recreate the necessary tables.
906  */
907 
908  if (vec_len (am->input_acl_vec_by_sw_if_index) > sw_if_index)
909  {
910  if (vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]) > 0)
911  {
912  acl_interface_in_enable_disable (am, sw_if_index, 0);
913  acl_interface_in_enable_disable (am, sw_if_index, 1);
914  }
915  }
916  if (vec_len (am->output_acl_vec_by_sw_if_index) > sw_if_index)
917  {
918  if (vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]) > 0)
919  {
920  acl_interface_out_enable_disable (am, sw_if_index, 0);
921  acl_interface_out_enable_disable (am, sw_if_index, 1);
922  }
923  }
924  return 0;
925 }
926 
927 
928 typedef struct
929 {
932  u8 mac_mask[6];
941  /* egress tables */
949 
950 static u32
951 macip_find_match_type (macip_match_type_t * mv, u8 * mac_mask, u8 prefix_len,
952  u8 is_ipv6)
953 {
954  u32 i;
955  if (mv)
956  {
957  for (i = 0; i < vec_len (mv); i++)
958  {
959  if ((mv[i].prefix_len == prefix_len) && (mv[i].is_ipv6 == is_ipv6)
960  && (0 == memcmp (mv[i].mac_mask, mac_mask, 6)))
961  {
962  return i;
963  }
964  }
965  }
966  return ~0;
967 }
968 
969 
970 /* Get metric used to sort match types.
971  The more specific and the more often seen - the bigger the metric */
972 static int
974 {
975  unsigned int mac_bits_set = 0;
976  unsigned int mac_byte;
977  int i;
978  for (i = 0; i < 6; i++)
979  {
980  mac_byte = m->mac_mask[i];
981  for (; mac_byte; mac_byte >>= 1)
982  mac_bits_set += mac_byte & 1;
983  }
984  /*
985  * Attempt to place the more specific and the more used rules on top.
986  * There are obvious caveat corner cases to this, but they do not
987  * seem to be sensible in real world (e.g. specific IPv4 with wildcard MAC
988  * going with a wildcard IPv4 with a specific MAC).
989  */
990  return m->prefix_len + mac_bits_set + m->is_ipv6 + 10 * m->count;
991 }
992 
993 static int
995 {
996  /* Ascending sort based on the metric values */
997  return match_type_metric (m1) - match_type_metric (m2);
998 }
999 
1000 /* Get the offset of L3 source within ethernet packet */
1001 static int
1003 {
1004  if (is6)
1005  return (sizeof (ethernet_header_t) +
1006  offsetof (ip6_header_t, src_address));
1007  else
1008  return (sizeof (ethernet_header_t) +
1009  offsetof (ip4_header_t, src_address));
1010 }
1011 
1012 static int
1014 {
1015  if (is6)
1016  return (sizeof (ethernet_header_t) +
1017  offsetof (ip6_header_t, dst_address));
1018  else
1019  return (sizeof (ethernet_header_t) +
1020  offsetof (ip4_header_t, dst_address));
1021 }
1022 
1023 /*
1024  * return if the is_permit value also requires to create the egress tables
1025  * For backwards compatibility, we keep the is_permit = 1 to only
1026  * create the ingress tables, and the new value of 3 will also
1027  * create the egress tables based on destination.
1028  */
1029 static int
1031 {
1032  return (is_permit == 3);
1033 }
1034 
1035 static int
1037 {
1038  macip_match_type_t *mvec = NULL;
1039  macip_match_type_t *mt;
1040  macip_acl_list_t *a = pool_elt_at_index (am->macip_acls, macip_acl_index);
1041  int i;
1042  u32 match_type_index;
1043  u32 last_table;
1044  u32 out_last_table;
1045  u8 mask[5 * 16];
1047 
1048  /* Count the number of different types of rules */
1049  for (i = 0; i < a->count; i++)
1050  {
1051  if (~0 ==
1052  (match_type_index =
1054  a->rules[i].src_prefixlen,
1055  a->rules[i].is_ipv6)))
1056  {
1057  match_type_index = vec_len (mvec);
1058  vec_validate (mvec, match_type_index);
1059  memcpy (mvec[match_type_index].mac_mask,
1060  a->rules[i].src_mac_mask, 6);
1061  mvec[match_type_index].prefix_len = a->rules[i].src_prefixlen;
1062  mvec[match_type_index].is_ipv6 = a->rules[i].is_ipv6;
1063  mvec[match_type_index].has_egress = 0;
1064  mvec[match_type_index].table_index = ~0;
1065  mvec[match_type_index].arp_table_index = ~0;
1066  mvec[match_type_index].dot1q_table_index = ~0;
1067  mvec[match_type_index].dot1ad_table_index = ~0;
1068  mvec[match_type_index].arp_dot1q_table_index = ~0;
1069  mvec[match_type_index].arp_dot1ad_table_index = ~0;
1070  mvec[match_type_index].out_table_index = ~0;
1071  mvec[match_type_index].out_arp_table_index = ~0;
1072  mvec[match_type_index].out_dot1q_table_index = ~0;
1073  mvec[match_type_index].out_dot1ad_table_index = ~0;
1074  mvec[match_type_index].out_arp_dot1q_table_index = ~0;
1075  mvec[match_type_index].out_arp_dot1ad_table_index = ~0;
1076  }
1077  mvec[match_type_index].count++;
1078  mvec[match_type_index].has_egress |=
1080  }
1081  /* Put the most frequently used tables last in the list so we can create classifier tables in reverse order */
1083  /* Create the classifier tables */
1084  last_table = ~0;
1085  out_last_table = ~0;
1086  /* First add ARP tables */
1087  vec_foreach (mt, mvec)
1088  {
1089  int mask_len;
1090  int is6 = mt->is_ipv6;
1091  int tags;
1092  u32 *last_tag_table;
1093  u32 *out_last_tag_table;
1094  u32 l3_offset;
1095 
1096  if (!is6)
1097  {
1098  /*
1099  0 1 2 3
1100  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
1101  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1102  | Destination Address |
1103  + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1104  | | |
1105  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
1106  | Source Address |
1107  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1108  | EtherType | Hardware Type |
1109  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1110  | Protocol Type | Hw addr len | Proto addr len|
1111  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1112  | Opcode | |
1113  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
1114  | Sender Hardware Address |
1115  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1116  | Sender Protocol Address |
1117  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1118  | Target Hardware Address |
1119  + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1120  | | TargetProtocolAddress |
1121  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1122  | |
1123  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1124  */
1125  for (tags = 2; tags >= 0; tags--)
1126  {
1127  clib_memset (mask, 0, sizeof (mask));
1128  /* source MAC address */
1129  memcpy (&mask[6], mt->mac_mask, 6);
1130 
1131  switch (tags)
1132  {
1133  case 0:
1134  default:
1135  clib_memset (&mask[12], 0xff, 2); /* ethernet protocol */
1136  l3_offset = 14;
1137  last_tag_table = &mt->arp_table_index;
1138  break;
1139  case 1:
1140  clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */
1141  clib_memset (&mask[16], 0xff, 2); /* ethernet protocol */
1142  l3_offset = 18;
1143  last_tag_table = &mt->arp_dot1q_table_index;
1144  break;
1145  case 2:
1146  clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */
1147  clib_memset (&mask[16], 0xff, 2); /* VLAN tag2 */
1148  clib_memset (&mask[20], 0xff, 2); /* ethernet protocol */
1149  l3_offset = 22;
1150  last_tag_table = &mt->arp_dot1ad_table_index;
1151  break;
1152  }
1153 
1154  /* sender hardware address within ARP */
1155  memcpy (&mask[l3_offset + 8], mt->mac_mask, 6);
1156  /* sender protocol address within ARP */
1157  for (i = 0; i < (mt->prefix_len / 8); i++)
1158  mask[l3_offset + 14 + i] = 0xff;
1159  if (mt->prefix_len % 8)
1160  mask[l3_offset + 14 + (mt->prefix_len / 8)] =
1161  0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
1162 
1163  mask_len = ((l3_offset + 14 + ((mt->prefix_len + 7) / 8) +
1164  (sizeof (u32x4) -
1165  1)) / sizeof (u32x4)) * sizeof (u32x4);
1166  acl_classify_add_del_table_small (cm, mask, mask_len, last_table,
1167  (~0 == last_table) ? 0 : ~0,
1168  last_tag_table, 1);
1169  last_table = *last_tag_table;
1170  if (mt->has_egress)
1171  {
1172  /* egress ARP table */
1173  clib_memset (mask, 0, sizeof (mask));
1174 
1175  switch (tags)
1176  {
1177  case 0:
1178  default:
1179  clib_memset (&mask[12], 0xff, 2); /* ethernet protocol */
1180  l3_offset = 14;
1181  out_last_tag_table = &mt->out_arp_table_index;
1182  break;
1183  case 1:
1184  clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */
1185  clib_memset (&mask[16], 0xff, 2); /* ethernet protocol */
1186  l3_offset = 18;
1187  out_last_tag_table = &mt->out_arp_dot1q_table_index;
1188  break;
1189  case 2:
1190  clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */
1191  clib_memset (&mask[16], 0xff, 2); /* VLAN tag2 */
1192  clib_memset (&mask[20], 0xff, 2); /* ethernet protocol */
1193  l3_offset = 22;
1194  out_last_tag_table = &mt->out_arp_dot1ad_table_index;
1195  break;
1196  }
1197 
1198  /* AYXX: FIXME here - can we tighten the ARP-related table more ? */
1199  /* mask captures just the destination and the ethertype */
1200  mask_len = ((l3_offset +
1201  (sizeof (u32x4) -
1202  1)) / sizeof (u32x4)) * sizeof (u32x4);
1203  acl_classify_add_del_table_small (cm, mask, mask_len,
1204  out_last_table,
1205  (~0 ==
1206  out_last_table) ? 0 : ~0,
1207  out_last_tag_table, 1);
1208  out_last_table = *out_last_tag_table;
1209  }
1210  }
1211  }
1212  }
1213  /* Now add IP[46] tables */
1214  vec_foreach (mt, mvec)
1215  {
1216  int mask_len;
1217  int is6 = mt->is_ipv6;
1218  int l3_src_offs;
1219  int l3_dst_offs;
1220  int tags;
1221  u32 *last_tag_table;
1222  u32 *out_last_tag_table;
1223 
1224  /*
1225  * create chained tables for VLAN (no-tags, dot1q and dot1ad) packets
1226  */
1227  for (tags = 2; tags >= 0; tags--)
1228  {
1229  clib_memset (mask, 0, sizeof (mask));
1230  memcpy (&mask[6], mt->mac_mask, 6);
1231  l3_src_offs = tags * 4 + get_l3_src_offset (is6);
1232  switch (tags)
1233  {
1234  case 0:
1235  default:
1236  clib_memset (&mask[12], 0xff, 2); /* ethernet protocol */
1237  last_tag_table = &mt->table_index;
1238  break;
1239  case 1:
1240  clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */
1241  clib_memset (&mask[16], 0xff, 2); /* ethernet protocol */
1242  last_tag_table = &mt->dot1q_table_index;
1243  break;
1244  case 2:
1245  clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */
1246  clib_memset (&mask[16], 0xff, 2); /* VLAN tag2 */
1247  clib_memset (&mask[20], 0xff, 2); /* ethernet protocol */
1248  last_tag_table = &mt->dot1ad_table_index;
1249  break;
1250  }
1251  for (i = 0; i < (mt->prefix_len / 8); i++)
1252  {
1253  mask[l3_src_offs + i] = 0xff;
1254  }
1255  if (mt->prefix_len % 8)
1256  {
1257  mask[l3_src_offs + (mt->prefix_len / 8)] =
1258  0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
1259  }
1260  /*
1261  * Round-up the number of bytes needed to store the prefix,
1262  * and round up the number of vectors too
1263  */
1264  mask_len = ((l3_src_offs + ((mt->prefix_len + 7) / 8) +
1265  (sizeof (u32x4) - 1)) / sizeof (u32x4)) * sizeof (u32x4);
1266  acl_classify_add_del_table_small (cm, mask, mask_len, last_table,
1267  (~0 == last_table) ? 0 : ~0,
1268  last_tag_table, 1);
1269  last_table = *last_tag_table;
1270  }
1271  if (mt->has_egress)
1272  {
1273  for (tags = 2; tags >= 0; tags--)
1274  {
1275  clib_memset (mask, 0, sizeof (mask));
1276  /* MAC destination */
1277  memcpy (&mask[0], mt->mac_mask, 6);
1278  l3_dst_offs = tags * 4 + get_l3_dst_offset (is6);
1279  switch (tags)
1280  {
1281  case 0:
1282  default:
1283  clib_memset (&mask[12], 0xff, 2); /* ethernet protocol */
1284  out_last_tag_table = &mt->out_table_index;
1285  break;
1286  case 1:
1287  clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */
1288  clib_memset (&mask[16], 0xff, 2); /* ethernet protocol */
1289  out_last_tag_table = &mt->out_dot1q_table_index;
1290  break;
1291  case 2:
1292  clib_memset (&mask[12], 0xff, 2); /* VLAN tag1 */
1293  clib_memset (&mask[16], 0xff, 2); /* VLAN tag2 */
1294  clib_memset (&mask[20], 0xff, 2); /* ethernet protocol */
1295  out_last_tag_table = &mt->out_dot1ad_table_index;
1296  break;
1297  }
1298  for (i = 0; i < (mt->prefix_len / 8); i++)
1299  {
1300  mask[l3_dst_offs + i] = 0xff;
1301  }
1302  if (mt->prefix_len % 8)
1303  {
1304  mask[l3_dst_offs + (mt->prefix_len / 8)] =
1305  0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
1306  }
1307  /*
1308  * Round-up the number of bytes needed to store the prefix,
1309  * and round up the number of vectors too
1310  */
1311  mask_len = ((l3_dst_offs + ((mt->prefix_len + 7) / 8) +
1312  (sizeof (u32x4) -
1313  1)) / sizeof (u32x4)) * sizeof (u32x4);
1314  acl_classify_add_del_table_small (cm, mask, mask_len,
1315  out_last_table,
1316  (~0 == out_last_table) ? 0 : ~0,
1317  out_last_tag_table, 1);
1318  out_last_table = *out_last_tag_table;
1319  }
1320  }
1321  }
1322  a->ip4_table_index = last_table;
1323  a->ip6_table_index = last_table;
1324  a->l2_table_index = last_table;
1325 
1326  a->out_ip4_table_index = out_last_table;
1327  a->out_ip6_table_index = out_last_table;
1328  a->out_l2_table_index = out_last_table;
1329 
1330  /* Populate the classifier tables with rules from the MACIP ACL */
1331  for (i = 0; i < a->count; i++)
1332  {
1333  u32 action = 0;
1334  u32 metadata = 0;
1335  int is6 = a->rules[i].is_ipv6;
1336  int l3_src_offs;
1337  int l3_dst_offs;
1338  u32 tag_table;
1339  int tags, eth;
1340 
1341  match_type_index =
1343  a->rules[i].src_prefixlen,
1344  a->rules[i].is_ipv6);
1345  ASSERT (match_type_index != ~0);
1346 
1347  for (tags = 2; tags >= 0; tags--)
1348  {
1349  clib_memset (mask, 0, sizeof (mask));
1350  l3_src_offs = tags * 4 + get_l3_src_offset (is6);
1351  memcpy (&mask[6], a->rules[i].src_mac, 6);
1352  switch (tags)
1353  {
1354  case 0:
1355  default:
1356  tag_table = mvec[match_type_index].table_index;
1357  eth = 12;
1358  break;
1359  case 1:
1360  tag_table = mvec[match_type_index].dot1q_table_index;
1361  mask[12] = 0x81;
1362  mask[13] = 0x00;
1363  eth = 16;
1364  break;
1365  case 2:
1366  tag_table = mvec[match_type_index].dot1ad_table_index;
1367  mask[12] = 0x88;
1368  mask[13] = 0xa8;
1369  mask[16] = 0x81;
1370  mask[17] = 0x00;
1371  eth = 20;
1372  break;
1373  }
1374  if (is6)
1375  {
1376  memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip6, 16);
1377  mask[eth] = 0x86;
1378  mask[eth + 1] = 0xdd;
1379  }
1380  else
1381  {
1382  memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip4, 4);
1383  mask[eth] = 0x08;
1384  mask[eth + 1] = 0x00;
1385  }
1386 
1387  /* add session to table mvec[match_type_index].table_index; */
1388  vnet_classify_add_del_session (cm, tag_table,
1389  mask, a->rules[i].is_permit ? ~0 : 0,
1390  i, 0, action, metadata, 1);
1391  clib_memset (&mask[12], 0, sizeof (mask) - 12);
1392  }
1393 
1394  /* add ARP table entry too */
1395  if (!is6 && (mvec[match_type_index].arp_table_index != ~0))
1396  {
1397  clib_memset (mask, 0, sizeof (mask));
1398  memcpy (&mask[6], a->rules[i].src_mac, 6);
1399 
1400  for (tags = 2; tags >= 0; tags--)
1401  {
1402  switch (tags)
1403  {
1404  case 0:
1405  default:
1406  tag_table = mvec[match_type_index].arp_table_index;
1407  mask[12] = 0x08;
1408  mask[13] = 0x06;
1409  l3_src_offs = 14;
1410  break;
1411  case 1:
1412  tag_table = mvec[match_type_index].arp_dot1q_table_index;
1413  mask[12] = 0x81;
1414  mask[13] = 0x00;
1415  mask[16] = 0x08;
1416  mask[17] = 0x06;
1417  l3_src_offs = 18;
1418  break;
1419  case 2:
1420  tag_table = mvec[match_type_index].arp_dot1ad_table_index;
1421  mask[12] = 0x88;
1422  mask[13] = 0xa8;
1423  mask[16] = 0x81;
1424  mask[17] = 0x00;
1425  mask[20] = 0x08;
1426  mask[21] = 0x06;
1427  l3_src_offs = 22;
1428  break;
1429  }
1430 
1431  memcpy (&mask[l3_src_offs + 8], a->rules[i].src_mac, 6);
1432  memcpy (&mask[l3_src_offs + 14], &a->rules[i].src_ip_addr.ip4,
1433  4);
1434  vnet_classify_add_del_session (cm, tag_table, mask,
1435  a->rules[i].is_permit ? ~0 : 0,
1436  i, 0, action, metadata, 1);
1437  }
1438  }
1440  {
1441  /* Add the egress entry with destination set */
1442  for (tags = 2; tags >= 0; tags--)
1443  {
1444  clib_memset (mask, 0, sizeof (mask));
1445  l3_dst_offs = tags * 4 + get_l3_dst_offset (is6);
1446  /* src mac in the other direction becomes dst */
1447  memcpy (&mask[0], a->rules[i].src_mac, 6);
1448  switch (tags)
1449  {
1450  case 0:
1451  default:
1452  tag_table = mvec[match_type_index].out_table_index;
1453  eth = 12;
1454  break;
1455  case 1:
1456  tag_table = mvec[match_type_index].out_dot1q_table_index;
1457  mask[12] = 0x81;
1458  mask[13] = 0x00;
1459  eth = 16;
1460  break;
1461  case 2:
1462  tag_table = mvec[match_type_index].out_dot1ad_table_index;
1463  mask[12] = 0x88;
1464  mask[13] = 0xa8;
1465  mask[16] = 0x81;
1466  mask[17] = 0x00;
1467  eth = 20;
1468  break;
1469  }
1470  if (is6)
1471  {
1472  memcpy (&mask[l3_dst_offs], &a->rules[i].src_ip_addr.ip6,
1473  16);
1474  mask[eth] = 0x86;
1475  mask[eth + 1] = 0xdd;
1476  }
1477  else
1478  {
1479  memcpy (&mask[l3_dst_offs], &a->rules[i].src_ip_addr.ip4,
1480  4);
1481  mask[eth] = 0x08;
1482  mask[eth + 1] = 0x00;
1483  }
1484 
1485  /* add session to table mvec[match_type_index].table_index; */
1486  vnet_classify_add_del_session (cm, tag_table,
1487  mask,
1488  a->rules[i].is_permit ? ~0 : 0,
1489  i, 0, action, metadata, 1);
1490  // clib_memset (&mask[12], 0, sizeof (mask) - 12);
1491  }
1492 
1493  /* add ARP table entry too */
1494  if (!is6 && (mvec[match_type_index].out_arp_table_index != ~0))
1495  {
1496  for (tags = 2; tags >= 0; tags--)
1497  {
1498  clib_memset (mask, 0, sizeof (mask));
1499  switch (tags)
1500  {
1501  case 0:
1502  default:
1503  tag_table = mvec[match_type_index].out_arp_table_index;
1504  mask[12] = 0x08;
1505  mask[13] = 0x06;
1506  break;
1507  case 1:
1508  tag_table =
1509  mvec[match_type_index].out_arp_dot1q_table_index;
1510  mask[12] = 0x81;
1511  mask[13] = 0x00;
1512  mask[16] = 0x08;
1513  mask[17] = 0x06;
1514  break;
1515  case 2:
1516  tag_table =
1517  mvec[match_type_index].out_arp_dot1ad_table_index;
1518  mask[12] = 0x88;
1519  mask[13] = 0xa8;
1520  mask[16] = 0x81;
1521  mask[17] = 0x00;
1522  mask[20] = 0x08;
1523  mask[21] = 0x06;
1524  break;
1525  }
1526 
1527  vnet_classify_add_del_session (cm, tag_table,
1528  mask,
1529  a->
1530  rules[i].is_permit ? ~0 : 0,
1531  i, 0, action, metadata, 1);
1532  }
1533  }
1534  }
1535  }
1536  return 0;
1537 }
1538 
1539 static void
1541 {
1543  macip_acl_list_t *a = pool_elt_at_index (am->macip_acls, macip_acl_index);
1544 
1545  if (a->ip4_table_index != ~0)
1546  {
1547  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0,
1548  &a->ip4_table_index, 0);
1549  a->ip4_table_index = ~0;
1550  }
1551  if (a->ip6_table_index != ~0)
1552  {
1553  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0,
1554  &a->ip6_table_index, 0);
1555  a->ip6_table_index = ~0;
1556  }
1557  if (a->l2_table_index != ~0)
1558  {
1559  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0, &a->l2_table_index,
1560  0);
1561  a->l2_table_index = ~0;
1562  }
1563  if (a->out_ip4_table_index != ~0)
1564  {
1565  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0,
1566  &a->out_ip4_table_index, 0);
1567  a->out_ip4_table_index = ~0;
1568  }
1569  if (a->out_ip6_table_index != ~0)
1570  {
1571  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0,
1572  &a->out_ip6_table_index, 0);
1573  a->out_ip6_table_index = ~0;
1574  }
1575  if (a->out_l2_table_index != ~0)
1576  {
1577  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0,
1578  &a->out_l2_table_index, 0);
1579  a->out_l2_table_index = ~0;
1580  }
1581 }
1582 
1583 static int
1585  int is_apply)
1586 {
1587  int rv = 0;
1588  int rv0 = 0;
1589  int i;
1590  macip_acl_list_t *a = pool_elt_at_index (am->macip_acls, acl_index);
1591 
1592  for (i = 0; i < vec_len (am->macip_acl_by_sw_if_index); i++)
1593  if (vec_elt (am->macip_acl_by_sw_if_index, i) == acl_index)
1594  {
1597  is_apply);
1598  /* return the first unhappy outcome but make try to plough through. */
1599  rv = rv || rv0;
1600  rv0 =
1603  a->out_l2_table_index, is_apply);
1604  /* return the first unhappy outcome but make try to plough through. */
1605  rv = rv || rv0;
1606  }
1607  return rv;
1608 }
1609 
1610 static int
1611 macip_acl_add_list (u32 count, vl_api_macip_acl_rule_t rules[],
1612  u32 * acl_list_index, u8 * tag)
1613 {
1614  acl_main_t *am = &acl_main;
1616  macip_acl_rule_t *r;
1617  macip_acl_rule_t *acl_new_rules = 0;
1618  int i;
1619  int rv = 0;
1620 
1621  if (*acl_list_index != ~0)
1622  {
1623  /* They supplied some number, let's see if this MACIP ACL exists */
1624  if (pool_is_free_index (am->macip_acls, *acl_list_index))
1625  {
1626  /* tried to replace a non-existent ACL, no point doing anything */
1627  clib_warning
1628  ("acl-plugin-error: Trying to replace nonexistent MACIP ACL %d (tag %s)",
1629  *acl_list_index, tag);
1630  return VNET_API_ERROR_NO_SUCH_ENTRY;
1631  }
1632  }
1633 
1634  if (0 == count)
1635  {
1636  clib_warning
1637  ("acl-plugin-warning: Trying to create empty MACIP ACL (tag %s)",
1638  tag);
1639  }
1640  /* if replacing the ACL, unapply the classifier tables first - they will be gone.. */
1641  if (~0 != *acl_list_index)
1642  rv = macip_maybe_apply_unapply_classifier_tables (am, *acl_list_index, 0);
1643  void *oldheap = acl_set_heap (am);
1644  /* Create and populate the rules */
1645  if (count > 0)
1646  vec_validate (acl_new_rules, count - 1);
1647 
1648  for (i = 0; i < count; i++)
1649  {
1650  r = &acl_new_rules[i];
1651  r->is_permit = rules[i].is_permit;
1652  r->is_ipv6 = rules[i].src_prefix.address.af;
1653  mac_address_decode (rules[i].src_mac, (mac_address_t *) & r->src_mac);
1654  mac_address_decode (rules[i].src_mac_mask,
1655  (mac_address_t *) & r->src_mac_mask);
1656  ip_address_decode (&rules[i].src_prefix.address, &r->src_ip_addr);
1657  r->src_prefixlen = rules[i].src_prefix.len;
1658  }
1659 
1660  if (~0 == *acl_list_index)
1661  {
1662  /* Get ACL index */
1664  clib_memset (a, 0, sizeof (*a));
1665  /* Will return the newly allocated ACL index */
1666  *acl_list_index = a - am->macip_acls;
1667  }
1668  else
1669  {
1670  a = pool_elt_at_index (am->macip_acls, *acl_list_index);
1671  if (a->rules)
1672  {
1673  vec_free (a->rules);
1674  }
1675  macip_destroy_classify_tables (am, *acl_list_index);
1676  }
1677 
1678  a->rules = acl_new_rules;
1679  a->count = count;
1680  memcpy (a->tag, tag, sizeof (a->tag));
1681 
1682  /* Create and populate the classifier tables */
1683  macip_create_classify_tables (am, *acl_list_index);
1684  clib_mem_set_heap (oldheap);
1685  /* If the ACL was already applied somewhere, reapply the newly created tables */
1686  rv = rv
1687  || macip_maybe_apply_unapply_classifier_tables (am, *acl_list_index, 1);
1688  return rv;
1689 }
1690 
1691 /* No check that sw_if_index denotes a valid interface - the callers
1692  * were supposed to validate.
1693  *
1694  * That said, if sw_if_index corresponds to an interface that exists at all,
1695  * this function must return errors accordingly if the ACL is not applied.
1696  */
1697 
1698 static int
1700 {
1701  int rv;
1702  u32 macip_acl_index;
1704 
1705  /* The vector is too short - MACIP ACL is not applied */
1706  if (sw_if_index >= vec_len (am->macip_acl_by_sw_if_index))
1707  return VNET_API_ERROR_NO_SUCH_ENTRY;
1708 
1709  macip_acl_index = am->macip_acl_by_sw_if_index[sw_if_index];
1710  /* No point in deleting MACIP ACL which is not applied */
1711  if (~0 == macip_acl_index)
1712  return VNET_API_ERROR_NO_SUCH_ENTRY;
1713 
1714  a = pool_elt_at_index (am->macip_acls, macip_acl_index);
1715  /* remove the classifier tables off the interface L2 ACL */
1716  rv =
1717  vnet_set_input_acl_intfc (am->vlib_main, sw_if_index, a->ip4_table_index,
1718  a->ip6_table_index, a->l2_table_index, 0);
1719  rv |=
1720  vnet_set_output_acl_intfc (am->vlib_main, sw_if_index,
1722  a->out_l2_table_index, 0);
1723  /* Unset the MACIP ACL index */
1725  /* macip_acl_interface_add_acl did a vec_add1() to this previously, so [sw_if_index] should be valid */
1726  u32 index = vec_search (am->sw_if_index_vec_by_macip_acl[macip_acl_index],
1727  sw_if_index);
1728  if (index != ~0)
1729  vec_del1 (am->sw_if_index_vec_by_macip_acl[macip_acl_index], index);
1730  return rv;
1731 }
1732 
1733 /* No check for validity of sw_if_index - the callers were supposed to validate */
1734 
1735 static int
1737  u32 macip_acl_index)
1738 {
1740  int rv;
1741  if (pool_is_free_index (am->macip_acls, macip_acl_index))
1742  {
1743  return VNET_API_ERROR_NO_SUCH_ENTRY;
1744  }
1745  void *oldheap = acl_set_heap (am);
1746  a = pool_elt_at_index (am->macip_acls, macip_acl_index);
1747  vec_validate_init_empty (am->macip_acl_by_sw_if_index, sw_if_index, ~0);
1748  vec_validate (am->sw_if_index_vec_by_macip_acl, macip_acl_index);
1749  vec_add1 (am->sw_if_index_vec_by_macip_acl[macip_acl_index], sw_if_index);
1750  clib_mem_set_heap (oldheap);
1751  /* If there already a MACIP ACL applied, unapply it */
1752  if (~0 != am->macip_acl_by_sw_if_index[sw_if_index])
1753  macip_acl_interface_del_acl (am, sw_if_index);
1754  am->macip_acl_by_sw_if_index[sw_if_index] = macip_acl_index;
1755 
1756  /* Apply the classifier tables for L2 ACLs */
1757  rv =
1758  vnet_set_input_acl_intfc (am->vlib_main, sw_if_index, a->ip4_table_index,
1759  a->ip6_table_index, a->l2_table_index, 1);
1760  rv |=
1761  vnet_set_output_acl_intfc (am->vlib_main, sw_if_index,
1763  a->out_l2_table_index, 1);
1764  return rv;
1765 }
1766 
1767 static int
1768 macip_acl_del_list (u32 acl_list_index)
1769 {
1770  acl_main_t *am = &acl_main;
1772  int i;
1773  if (pool_is_free_index (am->macip_acls, acl_list_index))
1774  {
1775  return VNET_API_ERROR_NO_SUCH_ENTRY;
1776  }
1777 
1778  /* delete any references to the ACL */
1779  for (i = 0; i < vec_len (am->macip_acl_by_sw_if_index); i++)
1780  {
1781  if (am->macip_acl_by_sw_if_index[i] == acl_list_index)
1782  {
1784  }
1785  }
1786 
1787  void *oldheap = acl_set_heap (am);
1788  /* Now that classifier tables are detached, clean them up */
1789  macip_destroy_classify_tables (am, acl_list_index);
1790 
1791  /* now we can delete the ACL itself */
1792  a = pool_elt_at_index (am->macip_acls, acl_list_index);
1793  if (a->rules)
1794  {
1795  vec_free (a->rules);
1796  }
1797  pool_put (am->macip_acls, a);
1798  clib_mem_set_heap (oldheap);
1799  return 0;
1800 }
1801 
1802 
1803 static int
1805  u32 acl_list_index)
1806 {
1807  acl_main_t *am = &acl_main;
1808  int rv = -1;
1809  if (is_add)
1810  {
1811  rv = macip_acl_interface_add_acl (am, sw_if_index, acl_list_index);
1812  }
1813  else
1814  {
1815  rv = macip_acl_interface_del_acl (am, sw_if_index);
1816  }
1817  return rv;
1818 }
1819 
1820 /*
1821  * If the client does not allocate enough memory for a variable-length
1822  * message, and then proceed to use it as if the full memory allocated,
1823  * absent the check we happily consume that on the VPP side, and go
1824  * along as if nothing happened. However, the resulting
1825  * effects range from just garbage in the API decode
1826  * (because the decoder snoops too far), to potential memory
1827  * corruptions.
1828  *
1829  * This verifies that the actual length of the message is
1830  * at least expected_len, and complains loudly if it is not.
1831  *
1832  * A failing check here is 100% a software bug on the API user side,
1833  * so we might as well yell.
1834  *
1835  */
1836 static int
1837 verify_message_len (void *mp, u32 expected_len, char *where)
1838 {
1839  u32 supplied_len = vl_msg_api_get_msg_length (mp);
1840  if (supplied_len < expected_len)
1841  {
1842  clib_warning ("%s: Supplied message length %d is less than expected %d",
1843  where, supplied_len, expected_len);
1844  return 0;
1845  }
1846  else
1847  {
1848  return 1;
1849  }
1850 }
1851 
1852 /* API message handler */
1853 static void
1855 {
1857  acl_main_t *am = &acl_main;
1858  int rv;
1859  u32 acl_list_index = ntohl (mp->acl_index);
1860  u32 acl_count = ntohl (mp->count);
1861  u32 expected_len = sizeof (*mp) + acl_count * sizeof (mp->r[0]);
1862 
1863  if (verify_message_len (mp, expected_len, "acl_add_replace"))
1864  {
1865  rv = acl_add_list (acl_count, mp->r, &acl_list_index, mp->tag);
1866  }
1867  else
1868  {
1869  rv = VNET_API_ERROR_INVALID_VALUE;
1870  }
1871 
1872  /* *INDENT-OFF* */
1873  REPLY_MACRO2(VL_API_ACL_ADD_REPLACE_REPLY,
1874  ({
1875  rmp->acl_index = htonl(acl_list_index);
1876  }));
1877  /* *INDENT-ON* */
1878 }
1879 
1880 static void
1882 {
1883  acl_main_t *am = &acl_main;
1884  vl_api_acl_del_reply_t *rmp;
1885  int rv;
1886 
1887  rv = acl_del_list (ntohl (mp->acl_index));
1888 
1889  REPLY_MACRO (VL_API_ACL_DEL_REPLY);
1890 }
1891 
1892 
1893 static void
1896 {
1897  acl_main_t *am = &acl_main;
1898  vl_api_acl_stats_intf_counters_enable_reply_t *rmp;
1899  int rv;
1900 
1902 
1903  REPLY_MACRO (VL_API_ACL_DEL_REPLY);
1904 }
1905 
1906 
1907 static void
1909 {
1910  acl_main_t *am = &acl_main;
1912  u32 sw_if_index = ntohl (mp->sw_if_index);
1913  vl_api_acl_interface_add_del_reply_t *rmp;
1914  int rv = -1;
1915 
1916  if (pool_is_free_index (im->sw_interfaces, sw_if_index))
1917  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1918  else
1919  rv =
1920  acl_interface_add_del_inout_acl (sw_if_index, mp->is_add,
1921  mp->is_input, ntohl (mp->acl_index));
1922 
1923  REPLY_MACRO (VL_API_ACL_INTERFACE_ADD_DEL_REPLY);
1924 }
1925 
1926 static void
1929 {
1930  acl_main_t *am = &acl_main;
1931  vl_api_acl_interface_set_acl_list_reply_t *rmp;
1932  int rv = 0;
1933  int i;
1935  u32 sw_if_index = ntohl (mp->sw_if_index);
1936 
1937  if (pool_is_free_index (im->sw_interfaces, sw_if_index))
1938  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1939  else
1940  {
1941  int may_clear_sessions = 1;
1942  for (i = 0; i < mp->count; i++)
1943  {
1944  if (acl_is_not_defined (am, ntohl (mp->acls[i])))
1945  {
1946  /* ACL does not exist, so we can not apply it */
1947  rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1948  }
1949  }
1950  if (0 == rv)
1951  {
1952  void *oldheap = acl_set_heap (am);
1953 
1954  u32 *in_acl_vec = 0;
1955  u32 *out_acl_vec = 0;
1956  for (i = 0; i < mp->count; i++)
1957  if (i < mp->n_input)
1958  vec_add1 (in_acl_vec, clib_net_to_host_u32 (mp->acls[i]));
1959  else
1960  vec_add1 (out_acl_vec, clib_net_to_host_u32 (mp->acls[i]));
1961 
1962  rv =
1963  acl_interface_set_inout_acl_list (am, sw_if_index, 0, out_acl_vec,
1964  &may_clear_sessions);
1965  rv = rv
1966  || acl_interface_set_inout_acl_list (am, sw_if_index, 1,
1967  in_acl_vec,
1968  &may_clear_sessions);
1969  vec_free (in_acl_vec);
1970  vec_free (out_acl_vec);
1971  clib_mem_set_heap (oldheap);
1972  }
1973  }
1974 
1975  REPLY_MACRO (VL_API_ACL_INTERFACE_SET_ACL_LIST_REPLY);
1976 }
1977 
1978 static void
1979 copy_acl_rule_to_api_rule (vl_api_acl_rule_t * api_rule, acl_rule_t * r)
1980 {
1981  api_rule->is_permit = r->is_permit;
1983  &api_rule->src_prefix.address);
1984  ip_address_encode (&r->dst, r->is_ipv6 ? IP46_TYPE_IP6 : IP46_TYPE_IP4,
1985  &api_rule->dst_prefix.address);
1986  api_rule->src_prefix.len = r->src_prefixlen;
1987  api_rule->dst_prefix.len = r->dst_prefixlen;
1988  api_rule->proto = r->proto;
1989  api_rule->srcport_or_icmptype_first = htons (r->src_port_or_type_first);
1990  api_rule->srcport_or_icmptype_last = htons (r->src_port_or_type_last);
1991  api_rule->dstport_or_icmpcode_first = htons (r->dst_port_or_code_first);
1992  api_rule->dstport_or_icmpcode_last = htons (r->dst_port_or_code_last);
1993  api_rule->tcp_flags_mask = r->tcp_flags_mask;
1994  api_rule->tcp_flags_value = r->tcp_flags_value;
1995 }
1996 
1997 static void
1999  acl_list_t * acl, u32 context)
2000 {
2002  vl_api_acl_rule_t *rules;
2003  int i;
2004  acl_rule_t *acl_rules = acl->rules;
2005  int msg_size = sizeof (*mp) + sizeof (mp->r[0]) * vec_len (acl_rules);
2006  void *oldheap = acl_set_heap (am);
2007 
2008  mp = vl_msg_api_alloc (msg_size);
2009  clib_memset (mp, 0, msg_size);
2010  mp->_vl_msg_id = ntohs (VL_API_ACL_DETAILS + am->msg_id_base);
2011 
2012  /* fill in the message */
2013  mp->context = context;
2014  mp->count = htonl (vec_len (acl_rules));
2015  mp->acl_index = htonl (acl - am->acls);
2016  memcpy (mp->tag, acl->tag, sizeof (mp->tag));
2017  // clib_memcpy (mp->r, acl->rules, acl->count * sizeof(acl->rules[0]));
2018  rules = mp->r;
2019  for (i = 0; i < vec_len (acl_rules); i++)
2020  {
2021  copy_acl_rule_to_api_rule (&rules[i], &acl_rules[i]);
2022  }
2023 
2024  clib_mem_set_heap (oldheap);
2025  vl_api_send_msg (reg, (u8 *) mp);
2026 }
2027 
2028 
2029 static void
2031 {
2032  acl_main_t *am = &acl_main;
2033  u32 acl_index;
2034  acl_list_t *acl;
2035  int rv = -1;
2036  vl_api_registration_t *reg;
2037 
2039  if (!reg)
2040  return;
2041 
2042  if (mp->acl_index == ~0)
2043  {
2044  /* *INDENT-OFF* */
2045  /* Just dump all ACLs */
2046  pool_foreach (acl, am->acls,
2047  ({
2048  send_acl_details(am, reg, acl, mp->context);
2049  }));
2050  /* *INDENT-ON* */
2051  }
2052  else
2053  {
2054  acl_index = ntohl (mp->acl_index);
2055  if (!pool_is_free_index (am->acls, acl_index))
2056  {
2057  acl = pool_elt_at_index (am->acls, acl_index);
2058  send_acl_details (am, reg, acl, mp->context);
2059  }
2060  }
2061 
2062  if (rv == -1)
2063  {
2064  /* FIXME API: should we signal an error here at all ? */
2065  return;
2066  }
2067 }
2068 
2069 static void
2071  vl_api_registration_t * reg,
2072  u32 sw_if_index, u32 context)
2073 {
2075  int msg_size;
2076  int n_input;
2077  int n_output;
2078  int count;
2079  int i = 0;
2080  void *oldheap = acl_set_heap (am);
2081 
2082  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
2083  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
2084 
2085  clib_mem_set_heap (oldheap);
2086 
2087  n_input = vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]);
2088  n_output = vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]);
2089  count = n_input + n_output;
2090 
2091  msg_size = sizeof (*mp);
2092  msg_size += sizeof (mp->acls[0]) * count;
2093 
2094  mp = vl_msg_api_alloc (msg_size);
2095  clib_memset (mp, 0, msg_size);
2096  mp->_vl_msg_id =
2097  ntohs (VL_API_ACL_INTERFACE_LIST_DETAILS + am->msg_id_base);
2098 
2099  /* fill in the message */
2100  mp->context = context;
2101  mp->sw_if_index = htonl (sw_if_index);
2102  mp->count = count;
2103  mp->n_input = n_input;
2104  for (i = 0; i < n_input; i++)
2105  {
2106  mp->acls[i] = htonl (am->input_acl_vec_by_sw_if_index[sw_if_index][i]);
2107  }
2108  for (i = 0; i < n_output; i++)
2109  {
2110  mp->acls[n_input + i] =
2111  htonl (am->output_acl_vec_by_sw_if_index[sw_if_index][i]);
2112  }
2113  vl_api_send_msg (reg, (u8 *) mp);
2114 }
2115 
2116 static void
2118  mp)
2119 {
2120  acl_main_t *am = &acl_main;
2121  vnet_sw_interface_t *swif;
2123 
2124  u32 sw_if_index;
2125  vl_api_registration_t *reg;
2126 
2128  if (!reg)
2129  return;
2130 
2131  if (mp->sw_if_index == ~0)
2132  {
2133  /* *INDENT-OFF* */
2134  pool_foreach (swif, im->sw_interfaces,
2135  ({
2136  send_acl_interface_list_details(am, reg, swif->sw_if_index, mp->context);
2137  }));
2138  /* *INDENT-ON* */
2139  }
2140  else
2141  {
2142  sw_if_index = ntohl (mp->sw_if_index);
2143  if (!pool_is_free_index (im->sw_interfaces, sw_if_index))
2144  send_acl_interface_list_details (am, reg, sw_if_index, mp->context);
2145  }
2146 }
2147 
2148 /* MACIP ACL API handlers */
2149 
2150 static void
2152 {
2154  acl_main_t *am = &acl_main;
2155  int rv;
2156  u32 acl_list_index = ~0;
2157  u32 acl_count = ntohl (mp->count);
2158  u32 expected_len = sizeof (*mp) + acl_count * sizeof (mp->r[0]);
2159 
2160  if (verify_message_len (mp, expected_len, "macip_acl_add"))
2161  {
2162  rv = macip_acl_add_list (acl_count, mp->r, &acl_list_index, mp->tag);
2163  }
2164  else
2165  {
2166  rv = VNET_API_ERROR_INVALID_VALUE;
2167  }
2168 
2169  /* *INDENT-OFF* */
2170  REPLY_MACRO2(VL_API_MACIP_ACL_ADD_REPLY,
2171  ({
2172  rmp->acl_index = htonl(acl_list_index);
2173  }));
2174  /* *INDENT-ON* */
2175 }
2176 
2177 static void
2179 {
2181  acl_main_t *am = &acl_main;
2182  int rv;
2183  u32 acl_list_index = ntohl (mp->acl_index);
2184  u32 acl_count = ntohl (mp->count);
2185  u32 expected_len = sizeof (*mp) + acl_count * sizeof (mp->r[0]);
2186 
2187  if (verify_message_len (mp, expected_len, "macip_acl_add_replace"))
2188  {
2189  rv = macip_acl_add_list (acl_count, mp->r, &acl_list_index, mp->tag);
2190  }
2191  else
2192  {
2193  rv = VNET_API_ERROR_INVALID_VALUE;
2194  }
2195 
2196  /* *INDENT-OFF* */
2197  REPLY_MACRO2(VL_API_MACIP_ACL_ADD_REPLACE_REPLY,
2198  ({
2199  rmp->acl_index = htonl(acl_list_index);
2200  }));
2201  /* *INDENT-ON* */
2202 }
2203 
2204 static void
2206 {
2207  acl_main_t *am = &acl_main;
2208  vl_api_macip_acl_del_reply_t *rmp;
2209  int rv;
2210 
2211  rv = macip_acl_del_list (ntohl (mp->acl_index));
2212 
2213  REPLY_MACRO (VL_API_MACIP_ACL_DEL_REPLY);
2214 }
2215 
2216 static void
2219 {
2220  acl_main_t *am = &acl_main;
2221  vl_api_macip_acl_interface_add_del_reply_t *rmp;
2222  int rv = -1;
2224  u32 sw_if_index = ntohl (mp->sw_if_index);
2225 
2226  if (pool_is_free_index (im->sw_interfaces, sw_if_index))
2227  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
2228  else
2229  rv =
2231  ntohl (mp->acl_index));
2232 
2233  REPLY_MACRO (VL_API_MACIP_ACL_INTERFACE_ADD_DEL_REPLY);
2234 }
2235 
2236 static void
2238  macip_acl_list_t * acl, u32 context)
2239 {
2241  vl_api_macip_acl_rule_t *rules;
2242  macip_acl_rule_t *r;
2243  int i;
2244  int msg_size = sizeof (*mp) + (acl ? sizeof (mp->r[0]) * acl->count : 0);
2245 
2246  mp = vl_msg_api_alloc (msg_size);
2247  clib_memset (mp, 0, msg_size);
2248  mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_DETAILS + am->msg_id_base);
2249 
2250  /* fill in the message */
2251  mp->context = context;
2252  if (acl)
2253  {
2254  memcpy (mp->tag, acl->tag, sizeof (mp->tag));
2255  mp->count = htonl (acl->count);
2256  mp->acl_index = htonl (acl - am->macip_acls);
2257  rules = mp->r;
2258  for (i = 0; i < acl->count; i++)
2259  {
2260  r = &acl->rules[i];
2261  rules[i].is_permit = r->is_permit;
2263  rules[i].src_mac);
2265  rules[i].src_mac_mask);
2268  &rules[i].src_prefix.address);
2269  rules[i].src_prefix.len = r->src_prefixlen;
2270  }
2271  }
2272  else
2273  {
2274  /* No martini, no party - no ACL applied to this interface. */
2275  mp->acl_index = ~0;
2276  mp->count = 0;
2277  }
2278 
2279  vl_api_send_msg (reg, (u8 *) mp);
2280 }
2281 
2282 
2283 static void
2285 {
2286  acl_main_t *am = &acl_main;
2287  macip_acl_list_t *acl;
2288 
2289  vl_api_registration_t *reg;
2290 
2292  if (!reg)
2293  return;
2294 
2295  if (mp->acl_index == ~0)
2296  {
2297  /* Just dump all ACLs for now, with sw_if_index = ~0 */
2298  /* *INDENT-OFF* */
2299  pool_foreach (acl, am->macip_acls,
2300  ({
2301  send_macip_acl_details (am, reg, acl, mp->context);
2302  }));
2303  /* *INDENT-ON* */
2304  }
2305  else
2306  {
2307  u32 acl_index = ntohl (mp->acl_index);
2308  if (!pool_is_free_index (am->macip_acls, acl_index))
2309  {
2310  acl = pool_elt_at_index (am->macip_acls, acl_index);
2311  send_macip_acl_details (am, reg, acl, mp->context);
2312  }
2313  }
2314 }
2315 
2316 static void
2318  mp)
2319 {
2320  acl_main_t *am = &acl_main;
2323  int msg_size = sizeof (*rmp) + sizeof (rmp->acls[0]) * count;
2324  vl_api_registration_t *reg;
2325  int i;
2326 
2328  if (!reg)
2329  return;
2330 
2331  rmp = vl_msg_api_alloc (msg_size);
2332  clib_memset (rmp, 0, msg_size);
2333  rmp->_vl_msg_id =
2334  ntohs (VL_API_MACIP_ACL_INTERFACE_GET_REPLY + am->msg_id_base);
2335  rmp->context = mp->context;
2336  rmp->count = htonl (count);
2337  for (i = 0; i < count; i++)
2338  {
2339  rmp->acls[i] = htonl (am->macip_acl_by_sw_if_index[i]);
2340  }
2341 
2342  vl_api_send_msg (reg, (u8 *) rmp);
2343 }
2344 
2345 static void
2347  vl_api_registration_t * reg,
2348  u32 sw_if_index,
2349  u32 acl_index, u32 context)
2350 {
2352  /* at this time there is only ever 1 mac ip acl per interface */
2353  int msg_size = sizeof (*rmp) + sizeof (rmp->acls[0]);
2354 
2355  rmp = vl_msg_api_alloc (msg_size);
2356  clib_memset (rmp, 0, msg_size);
2357  rmp->_vl_msg_id =
2358  ntohs (VL_API_MACIP_ACL_INTERFACE_LIST_DETAILS + am->msg_id_base);
2359 
2360  /* fill in the message */
2361  rmp->context = context;
2362  rmp->count = 1;
2363  rmp->sw_if_index = htonl (sw_if_index);
2364  rmp->acls[0] = htonl (acl_index);
2365 
2366  vl_api_send_msg (reg, (u8 *) rmp);
2367 }
2368 
2369 static void
2372 {
2373  vl_api_registration_t *reg;
2374  acl_main_t *am = &acl_main;
2375  u32 sw_if_index = ntohl (mp->sw_if_index);
2376 
2378  if (!reg)
2379  return;
2380 
2381  if (sw_if_index == ~0)
2382  {
2383  vec_foreach_index (sw_if_index, am->macip_acl_by_sw_if_index)
2384  {
2385  if (~0 != am->macip_acl_by_sw_if_index[sw_if_index])
2386  {
2387  send_macip_acl_interface_list_details (am, reg, sw_if_index,
2389  [sw_if_index],
2390  mp->context);
2391  }
2392  }
2393  }
2394  else
2395  {
2396  if (vec_len (am->macip_acl_by_sw_if_index) > sw_if_index)
2397  {
2398  send_macip_acl_interface_list_details (am, reg, sw_if_index,
2400  [sw_if_index], mp->context);
2401  }
2402  }
2403 }
2404 
2405 static void
2408 {
2409  acl_main_t *am = &acl_main;
2410  vl_api_acl_interface_set_etype_whitelist_reply_t *rmp;
2411  int rv = 0;
2412  int i;
2414  u32 sw_if_index = ntohl (mp->sw_if_index);
2415  u16 *vec_in = 0, *vec_out = 0;
2416  void *oldheap = acl_set_heap (am);
2417 
2418  if (pool_is_free_index (im->sw_interfaces, sw_if_index))
2419  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
2420  else
2421  {
2422  for (i = 0; i < mp->count; i++)
2423  {
2424  if (i < mp->n_input)
2425  vec_add1 (vec_in, ntohs (mp->whitelist[i]));
2426  else
2427  vec_add1 (vec_out, ntohs (mp->whitelist[i]));
2428  }
2429  rv = acl_set_etype_whitelists (am, sw_if_index, vec_in, vec_out);
2430  }
2431 
2432  clib_mem_set_heap (oldheap);
2433  REPLY_MACRO (VL_API_ACL_INTERFACE_SET_ETYPE_WHITELIST_REPLY);
2434 }
2435 
2436 static void
2438  vl_api_registration_t * reg,
2439  u32 sw_if_index, u32 context)
2440 {
2442  int msg_size;
2443  int n_input = 0;
2444  int n_output = 0;
2445  int count = 0;
2446  int i = 0;
2447 
2448  u16 *whitelist_in = 0;
2449  u16 *whitelist_out = 0;
2450 
2451  if (intf_has_etype_whitelist (am, sw_if_index, 0))
2452  whitelist_out =
2454 
2455  if (intf_has_etype_whitelist (am, sw_if_index, 1))
2456  whitelist_in =
2457  vec_elt (am->input_etype_whitelist_by_sw_if_index, sw_if_index);
2458 
2459  if ((0 == whitelist_in) && (0 == whitelist_out))
2460  return; /* nothing to do */
2461 
2462  void *oldheap = acl_set_heap (am);
2463 
2464  n_input = vec_len (whitelist_in);
2465  n_output = vec_len (whitelist_out);
2466  count = n_input + n_output;
2467 
2468  msg_size = sizeof (*mp);
2469  msg_size += sizeof (mp->whitelist[0]) * count;
2470 
2471  mp = vl_msg_api_alloc (msg_size);
2472  clib_memset (mp, 0, msg_size);
2473  mp->_vl_msg_id =
2474  ntohs (VL_API_ACL_INTERFACE_ETYPE_WHITELIST_DETAILS + am->msg_id_base);
2475 
2476  /* fill in the message */
2477  mp->context = context;
2478  mp->sw_if_index = htonl (sw_if_index);
2479  mp->count = count;
2480  mp->n_input = n_input;
2481  for (i = 0; i < n_input; i++)
2482  {
2483  mp->whitelist[i] = htons (whitelist_in[i]);
2484  }
2485  for (i = 0; i < n_output; i++)
2486  {
2487  mp->whitelist[n_input + i] = htons (whitelist_out[i]);
2488  }
2489  clib_mem_set_heap (oldheap);
2490  vl_api_send_msg (reg, (u8 *) mp);
2491 }
2492 
2493 
2494 static void
2497 {
2498  acl_main_t *am = &acl_main;
2499  vnet_sw_interface_t *swif;
2501 
2502  u32 sw_if_index;
2503  vl_api_registration_t *reg;
2504 
2506  if (!reg)
2507  return;
2508 
2509  if (mp->sw_if_index == ~0)
2510  {
2511  /* *INDENT-OFF* */
2512  pool_foreach (swif, im->sw_interfaces,
2513  ({
2514  send_acl_interface_etype_whitelist_details(am, reg, swif->sw_if_index, mp->context);
2515  }));
2516  /* *INDENT-ON* */
2517  }
2518  else
2519  {
2520  sw_if_index = ntohl (mp->sw_if_index);
2521  if (!pool_is_free_index (im->sw_interfaces, sw_if_index))
2522  send_acl_interface_etype_whitelist_details (am, reg, sw_if_index,
2523  mp->context);
2524  }
2525 }
2526 
2527 static void
2528 acl_set_timeout_sec (int timeout_type, u32 value)
2529 {
2530  acl_main_t *am = &acl_main;
2531  clib_time_t *ct = &am->vlib_main->clib_time;
2532 
2533  if (timeout_type < ACL_N_TIMEOUTS)
2534  {
2535  am->session_timeout_sec[timeout_type] = value;
2536  }
2537  else
2538  {
2539  clib_warning ("Unknown timeout type %d", timeout_type);
2540  return;
2541  }
2542  am->session_timeout[timeout_type] =
2543  (u64) (((f64) value) / ct->seconds_per_clock);
2544 }
2545 
2546 static void
2548 {
2549  acl_main_t *am = &acl_main;
2551 }
2552 
2553 static int
2555 {
2556  acl_main_t *am = &acl_main;
2557 
2558  if ((eh < 256) && (value < 2))
2559  {
2561  clib_bitmap_set (am->fa_ipv6_known_eh_bitmap, eh, value);
2562  return 1;
2563  }
2564  else
2565  return 0;
2566 }
2567 
2568 
2569 static clib_error_t *
2571 {
2572  acl_main_t *am = &acl_main;
2573  if (0 == am->acl_mheap)
2574  {
2575  /* ACL heap is not initialized, so definitely nothing to do. */
2576  return 0;
2577  }
2578  if (0 == is_add)
2579  {
2580  int may_clear_sessions = 1;
2583  sw_if_index);
2584  /* also unapply any ACLs in case the users did not do so. */
2585  macip_acl_interface_del_acl (am, sw_if_index);
2586  acl_interface_reset_inout_acls (sw_if_index, 0, &may_clear_sessions);
2587  acl_interface_reset_inout_acls (sw_if_index, 1, &may_clear_sessions);
2588  }
2589  return 0;
2590 }
2591 
2593 
2594 
2595 
2596 static clib_error_t *
2598  unformat_input_t * input, vlib_cli_command_t * cmd)
2599 {
2600  clib_error_t *error = 0;
2601  u32 timeout = 0;
2602  u32 val = 0;
2603  u32 eh_val = 0;
2604  uword memory_size = 0;
2605  acl_main_t *am = &acl_main;
2606 
2607  if (unformat (input, "skip-ipv6-extension-header %u %u", &eh_val, &val))
2608  {
2609  if (!acl_set_skip_ipv6_eh (eh_val, val))
2610  {
2611  error = clib_error_return (0, "expecting eh=0..255, value=0..1");
2612  }
2613  goto done;
2614  }
2615  if (unformat (input, "use-hash-acl-matching %u", &val))
2616  {
2617  am->use_hash_acl_matching = (val != 0);
2618  goto done;
2619  }
2620  if (unformat (input, "l4-match-nonfirst-fragment %u", &val))
2621  {
2622  am->l4_match_nonfirst_fragment = (val != 0);
2623  goto done;
2624  }
2625  if (unformat (input, "reclassify-sessions %u", &val))
2626  {
2627  am->reclassify_sessions = (val != 0);
2628  goto done;
2629  }
2630  if (unformat (input, "event-trace"))
2631  {
2632  if (!unformat (input, "%u", &val))
2633  {
2634  error = clib_error_return (0,
2635  "expecting trace level, got `%U`",
2636  format_unformat_error, input);
2637  goto done;
2638  }
2639  else
2640  {
2641  am->trace_acl = val;
2642  goto done;
2643  }
2644  }
2645  if (unformat (input, "heap"))
2646  {
2647  if (unformat (input, "main"))
2648  {
2649  if (unformat (input, "validate %u", &val))
2651  else if (unformat (input, "trace %u", &val))
2653  goto done;
2654  }
2655  else if (unformat (input, "hash"))
2656  {
2657  if (unformat (input, "validate %u", &val))
2659  else if (unformat (input, "trace %u", &val))
2661  goto done;
2662  }
2663  goto done;
2664  }
2665  if (unformat (input, "session"))
2666  {
2667  if (unformat (input, "table"))
2668  {
2669  /* The commands here are for tuning/testing. No user-serviceable parts inside */
2670  if (unformat (input, "max-entries"))
2671  {
2672  if (!unformat (input, "%u", &val))
2673  {
2674  error = clib_error_return (0,
2675  "expecting maximum number of entries, got `%U`",
2676  format_unformat_error, input);
2677  goto done;
2678  }
2679  else
2680  {
2682  goto done;
2683  }
2684  }
2685  if (unformat (input, "hash-table-buckets"))
2686  {
2687  if (!unformat (input, "%u", &val))
2688  {
2689  error = clib_error_return (0,
2690  "expecting maximum number of hash table buckets, got `%U`",
2691  format_unformat_error, input);
2692  goto done;
2693  }
2694  else
2695  {
2697  goto done;
2698  }
2699  }
2700  if (unformat (input, "hash-table-memory"))
2701  {
2702  if (!unformat (input, "%U", unformat_memory_size, &memory_size))
2703  {
2704  error = clib_error_return (0,
2705  "expecting maximum amount of hash table memory, got `%U`",
2706  format_unformat_error, input);
2707  goto done;
2708  }
2709  else
2710  {
2712  goto done;
2713  }
2714  }
2715  if (unformat (input, "event-trace"))
2716  {
2717  if (!unformat (input, "%u", &val))
2718  {
2719  error = clib_error_return (0,
2720  "expecting trace level, got `%U`",
2721  format_unformat_error, input);
2722  goto done;
2723  }
2724  else
2725  {
2726  am->trace_sessions = val;
2727  goto done;
2728  }
2729  }
2730  goto done;
2731  }
2732  if (unformat (input, "timeout"))
2733  {
2734  if (unformat (input, "udp"))
2735  {
2736  if (unformat (input, "idle"))
2737  {
2738  if (!unformat (input, "%u", &timeout))
2739  {
2740  error = clib_error_return (0,
2741  "expecting timeout value in seconds, got `%U`",
2743  input);
2744  goto done;
2745  }
2746  else
2747  {
2749  goto done;
2750  }
2751  }
2752  }
2753  if (unformat (input, "tcp"))
2754  {
2755  if (unformat (input, "idle"))
2756  {
2757  if (!unformat (input, "%u", &timeout))
2758  {
2759  error = clib_error_return (0,
2760  "expecting timeout value in seconds, got `%U`",
2762  input);
2763  goto done;
2764  }
2765  else
2766  {
2768  goto done;
2769  }
2770  }
2771  if (unformat (input, "transient"))
2772  {
2773  if (!unformat (input, "%u", &timeout))
2774  {
2775  error = clib_error_return (0,
2776  "expecting timeout value in seconds, got `%U`",
2778  input);
2779  goto done;
2780  }
2781  else
2782  {
2784  timeout);
2785  goto done;
2786  }
2787  }
2788  }
2789  goto done;
2790  }
2791  }
2792 done:
2793  return error;
2794 }
2795 
2796 static u8 *
2797 my_format_mac_address (u8 * s, va_list * args)
2798 {
2799  u8 *a = va_arg (*args, u8 *);
2800  return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
2801  a[0], a[1], a[2], a[3], a[4], a[5]);
2802 }
2803 
2804 static inline u8 *
2805 my_macip_acl_rule_t_pretty_format (u8 * out, va_list * args)
2806 {
2807  macip_acl_rule_t *a = va_arg (*args, macip_acl_rule_t *);
2808 
2809  out = format (out, "%s action %d ip %U/%d mac %U mask %U",
2810  a->is_ipv6 ? "ipv6" : "ipv4", a->is_permit,
2813  a->src_prefixlen,
2816  return (out);
2817 }
2818 
2819 static void
2820 macip_acl_print (acl_main_t * am, u32 macip_acl_index)
2821 {
2822  vlib_main_t *vm = am->vlib_main;
2823  int i;
2824 
2825  /* Don't try to print someone else's memory */
2826  if (macip_acl_index >= vec_len (am->macip_acls))
2827  return;
2828 
2829  macip_acl_list_t *a = vec_elt_at_index (am->macip_acls, macip_acl_index);
2830  int free_pool_slot = pool_is_free_index (am->macip_acls, macip_acl_index);
2831 
2832  vlib_cli_output (vm,
2833  "MACIP acl_index: %d, count: %d (true len %d) tag {%s} is free pool slot: %d\n",
2834  macip_acl_index, a->count, vec_len (a->rules), a->tag,
2835  free_pool_slot);
2836  vlib_cli_output (vm,
2837  " ip4_table_index %d, ip6_table_index %d, l2_table_index %d\n",
2839  vlib_cli_output (vm,
2840  " out_ip4_table_index %d, out_ip6_table_index %d, out_l2_table_index %d\n",
2842  a->out_l2_table_index);
2843  for (i = 0; i < vec_len (a->rules); i++)
2844  vlib_cli_output (vm, " rule %d: %U\n", i,
2846  vec_elt_at_index (a->rules, i));
2847 
2848 }
2849 
2850 static clib_error_t *
2852  unformat_input_t * input,
2853  vlib_cli_command_t * cmd)
2854 {
2855  unformat_input_t _line_input, *line_input = &_line_input;
2856  u32 sw_if_index, is_add, is_input, acl_index;
2857 
2858  is_add = is_input = 1;
2859  acl_index = sw_if_index = ~0;
2860 
2861  if (!unformat_user (input, unformat_line_input, line_input))
2862  return 0;
2863 
2864  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2865  {
2866  if (unformat (line_input, "%U",
2868  &sw_if_index))
2869  ;
2870  else if (unformat (line_input, "add"))
2871  is_add = 1;
2872  else if (unformat (line_input, "del"))
2873  is_add = 0;
2874  else if (unformat (line_input, "acl %d", &acl_index))
2875  ;
2876  else if (unformat (line_input, "input"))
2877  is_input = 1;
2878  else if (unformat (line_input, "output"))
2879  is_input = 0;
2880  else
2881  break;
2882  }
2883 
2884  if (~0 == sw_if_index)
2885  return (clib_error_return (0, "invalid interface"));
2886  if (~0 == acl_index)
2887  return (clib_error_return (0, "invalid acl"));
2888 
2889  acl_interface_add_del_inout_acl (sw_if_index, is_add, is_input, acl_index);
2890 
2891  unformat_free (line_input);
2892  return (NULL);
2893 }
2894 
2895 #define vec_validate_acl_rules(v, idx) \
2896  do { \
2897  if (vec_len(v) < idx+1) { \
2898  vec_validate(v, idx); \
2899  v[idx].is_permit = 0x1; \
2900  v[idx].srcport_or_icmptype_last = 0xffff; \
2901  v[idx].dstport_or_icmpcode_last = 0xffff; \
2902  } \
2903  } while (0)
2904 
2905 static clib_error_t *
2907  unformat_input_t * input, vlib_cli_command_t * cmd)
2908 {
2909  unformat_input_t _line_input, *line_input = &_line_input;
2910  vl_api_acl_rule_t *rules = 0;
2911  int rv;
2912  int rule_idx = 0;
2913  int n_rules_override = -1;
2914  u32 proto = 0;
2915  u32 port1 = 0;
2916  u32 port2 = 0;
2917  u32 action = 0;
2918  u32 tcpflags, tcpmask;
2919  u32 src_prefix_length = 0, dst_prefix_length = 0;
2920  ip46_address_t src, dst;
2921  u8 *tag = (u8 *) "cli";
2922 
2923  if (!unformat_user (input, unformat_line_input, line_input))
2924  return 0;
2925 
2926  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2927  {
2928  if (unformat (line_input, "permit+reflect"))
2929  {
2930  vec_validate_acl_rules (rules, rule_idx);
2931  rules[rule_idx].is_permit = 2;
2932  }
2933  else if (unformat (line_input, "permit"))
2934  {
2935  vec_validate_acl_rules (rules, rule_idx);
2936  rules[rule_idx].is_permit = 1;
2937  }
2938  else if (unformat (line_input, "deny"))
2939  {
2940  vec_validate_acl_rules (rules, rule_idx);
2941  rules[rule_idx].is_permit = 0;
2942  }
2943  else if (unformat (line_input, "count %d", &n_rules_override))
2944  {
2945  /* we will use this later */
2946  }
2947  else if (unformat (line_input, "action %d", &action))
2948  {
2949  vec_validate_acl_rules (rules, rule_idx);
2950  rules[rule_idx].is_permit = action;
2951  }
2952  else if (unformat (line_input, "src %U/%d",
2954  &src_prefix_length))
2955  {
2956  vec_validate_acl_rules (rules, rule_idx);
2958  &rules[rule_idx].src_prefix.address);
2959  rules[rule_idx].src_prefix.address.af = ADDRESS_IP4;
2960  rules[rule_idx].src_prefix.len = src_prefix_length;
2961  }
2962  else if (unformat (line_input, "dst %U/%d",
2964  &dst_prefix_length))
2965  {
2966  vec_validate_acl_rules (rules, rule_idx);
2968  &rules[rule_idx].dst_prefix.address);
2969  rules[rule_idx].dst_prefix.address.af = ADDRESS_IP4;
2970  rules[rule_idx].dst_prefix.len = dst_prefix_length;
2971  }
2972  else if (unformat (line_input, "sport %d-%d", &port1, &port2))
2973  {
2974  vec_validate_acl_rules (rules, rule_idx);
2975  rules[rule_idx].srcport_or_icmptype_first = htons (port1);
2976  rules[rule_idx].srcport_or_icmptype_last = htons (port2);
2977  }
2978  else if (unformat (line_input, "sport %d", &port1))
2979  {
2980  vec_validate_acl_rules (rules, rule_idx);
2981  rules[rule_idx].srcport_or_icmptype_first = htons (port1);
2982  rules[rule_idx].srcport_or_icmptype_last = htons (port1);
2983  }
2984  else if (unformat (line_input, "dport %d-%d", &port1, &port2))
2985  {
2986  vec_validate_acl_rules (rules, rule_idx);
2987  rules[rule_idx].dstport_or_icmpcode_first = htons (port1);
2988  rules[rule_idx].dstport_or_icmpcode_last = htons (port2);
2989  }
2990  else if (unformat (line_input, "dport %d", &port1))
2991  {
2992  vec_validate_acl_rules (rules, rule_idx);
2993  rules[rule_idx].dstport_or_icmpcode_first = htons (port1);
2994  rules[rule_idx].dstport_or_icmpcode_last = htons (port1);
2995  }
2996  else if (unformat (line_input, "tcpflags %d %d", &tcpflags, &tcpmask))
2997  {
2998  vec_validate_acl_rules (rules, rule_idx);
2999  rules[rule_idx].tcp_flags_value = tcpflags;
3000  rules[rule_idx].tcp_flags_mask = tcpmask;
3001  }
3002  else
3003  if (unformat (line_input, "tcpflags %d mask %d", &tcpflags, &tcpmask))
3004  {
3005  vec_validate_acl_rules (rules, rule_idx);
3006  rules[rule_idx].tcp_flags_value = tcpflags;
3007  rules[rule_idx].tcp_flags_mask = tcpmask;
3008  }
3009  else if (unformat (line_input, "proto %d", &proto))
3010  {
3011  vec_validate_acl_rules (rules, rule_idx);
3012  rules[rule_idx].proto = proto;
3013  }
3014  else if (unformat (line_input, "tag %s", &tag))
3015  {
3016  }
3017  else if (unformat (line_input, ","))
3018  {
3019  rule_idx++;
3020  vec_validate_acl_rules (rules, rule_idx);
3021  }
3022  else
3023  break;
3024  }
3025 
3026  u32 acl_index = ~0;
3027 
3028  rv = acl_add_list (vec_len (rules), rules, &acl_index, tag);
3029 
3030  vec_free (rules);
3031 
3032  if (rv)
3033  return (clib_error_return (0, "failed"));
3034 
3035  vlib_cli_output (vm, "ACL index:%d", acl_index);
3036 
3037  return (NULL);
3038 }
3039 
3040 static clib_error_t *
3043  input, vlib_cli_command_t * cmd)
3044 {
3045  clib_error_t *error = 0;
3046  acl_main_t *am = &acl_main;
3047  int i;
3048  u32 acl_index = ~0;
3049 
3050  (void) unformat (input, "index %u", &acl_index);
3051 
3052  for (i = 0; i < vec_len (am->macip_acls); i++)
3053  {
3054  /* Don't attempt to show the ACLs that do not exist */
3055  if (pool_is_free_index (am->macip_acls, i))
3056  continue;
3057 
3058  if ((acl_index != ~0) && (acl_index != i))
3059  {
3060  continue;
3061  }
3062 
3063  macip_acl_print (am, i);
3064  if (i < vec_len (am->sw_if_index_vec_by_macip_acl))
3065  {
3066  vlib_cli_output (vm, " applied on sw_if_index(s): %U\n",
3067  format_vec32,
3069  "%d");
3070  }
3071  }
3072 
3073  return error;
3074 }
3075 
3076 static clib_error_t *
3079  input, vlib_cli_command_t * cmd)
3080 {
3081  clib_error_t *error = 0;
3082  acl_main_t *am = &acl_main;
3083  int i;
3084  for (i = 0; i < vec_len (am->macip_acl_by_sw_if_index); i++)
3085  {
3086  vlib_cli_output (vm, " sw_if_index %d: %d\n", i,
3088  }
3089  return error;
3090 }
3091 
3092 static void
3094 {
3095  u32 i;
3096  vlib_main_t *vm = am->vlib_main;
3097 
3098  for (i = 0; i < vec_len (am->acls); i++)
3099  {
3100  if (acl_is_not_defined (am, i))
3101  {
3102  /* don't attempt to show the ACLs that do not exist */
3103  continue;
3104  }
3105  if ((acl_index != ~0) && (acl_index != i))
3106  {
3107  continue;
3108  }
3109  acl_print_acl (vm, am, i);
3110 
3111  if (i < vec_len (am->input_sw_if_index_vec_by_acl))
3112  {
3113  vlib_cli_output (vm, " applied inbound on sw_if_index: %U\n",
3115  "%d");
3116  }
3117  if (i < vec_len (am->output_sw_if_index_vec_by_acl))
3118  {
3119  vlib_cli_output (vm, " applied outbound on sw_if_index: %U\n",
3121  "%d");
3122  }
3123  if (i < vec_len (am->lc_index_vec_by_acl))
3124  {
3125  vlib_cli_output (vm, " used in lookup context index: %U\n",
3126  format_vec32, am->lc_index_vec_by_acl[i], "%d");
3127  }
3128  }
3129 }
3130 
3131 static clib_error_t *
3133  unformat_input_t * input, vlib_cli_command_t * cmd)
3134 {
3135  clib_error_t *error = 0;
3136  acl_main_t *am = &acl_main;
3137 
3138  u32 acl_index = ~0;
3139  (void) unformat (input, "index %u", &acl_index);
3140 
3141  acl_plugin_show_acl (am, acl_index);
3142  return error;
3143 }
3144 
3145 static clib_error_t *
3147  unformat_input_t * input,
3148  vlib_cli_command_t * cmd)
3149 {
3150  clib_error_t *error = 0;
3151 
3152  u32 lc_index = ~0;
3153  (void) unformat (input, "index %u", &lc_index);
3154 
3155  acl_plugin_show_lookup_context (lc_index);
3156  return error;
3157 }
3158 
3159 static clib_error_t *
3161  unformat_input_t * input,
3162  vlib_cli_command_t * cmd)
3163 {
3164  clib_error_t *error = 0;
3165 
3166  u32 lc_index = ~0;
3167  (void) unformat (input, "index %u", &lc_index);
3168 
3169  acl_plugin_show_lookup_user (lc_index);
3170  return error;
3171 }
3172 
3173 
3174 static void
3176  int detail)
3177 {
3178  vlib_main_t *vm = am->vlib_main;
3179  u32 swi;
3180  u32 *pj;
3181  for (swi = 0; (swi < vec_len (am->input_acl_vec_by_sw_if_index)) ||
3182  (swi < vec_len (am->output_acl_vec_by_sw_if_index)); swi++)
3183  {
3184  /* if we need a particular interface, skip all the others */
3185  if ((sw_if_index != ~0) && (sw_if_index != swi))
3186  continue;
3187 
3188  vlib_cli_output (vm, "sw_if_index %d:\n", swi);
3190  vlib_cli_output (vm, " input policy epoch: %x\n",
3192  swi));
3194  vlib_cli_output (vm, " output policy epoch: %x\n",
3196  swi));
3197 
3198 
3199  if (intf_has_etype_whitelist (am, swi, 1))
3200  {
3201  vlib_cli_output (vm, " input etype whitelist: %U", format_vec16,
3203  "%04x");
3204  }
3205  if (intf_has_etype_whitelist (am, swi, 0))
3206  {
3207  vlib_cli_output (vm, " output etype whitelist: %U", format_vec16,
3209  "%04x");
3210  }
3211 
3212  if ((swi < vec_len (am->input_acl_vec_by_sw_if_index)) &&
3213  (vec_len (am->input_acl_vec_by_sw_if_index[swi]) > 0))
3214  {
3215  vlib_cli_output (vm, " input acl(s): %U", format_vec32,
3216  am->input_acl_vec_by_sw_if_index[swi], "%d");
3217  if (show_acl)
3218  {
3219  vlib_cli_output (vm, "\n");
3221  {
3222  acl_print_acl (vm, am, *pj);
3223  }
3224  vlib_cli_output (vm, "\n");
3225  }
3226  }
3227 
3228  if ((swi < vec_len (am->output_acl_vec_by_sw_if_index)) &&
3229  (vec_len (am->output_acl_vec_by_sw_if_index[swi]) > 0))
3230  {
3231  vlib_cli_output (vm, " output acl(s): %U", format_vec32,
3232  am->output_acl_vec_by_sw_if_index[swi], "%d");
3233  if (show_acl)
3234  {
3235  vlib_cli_output (vm, "\n");
3237  {
3238  acl_print_acl (vm, am, *pj);
3239  }
3240  vlib_cli_output (vm, "\n");
3241  }
3242  }
3243  if (detail && (swi < vec_len (am->input_lc_index_by_sw_if_index)))
3244  {
3245  vlib_cli_output (vm, " input lookup context index: %d",
3247  }
3248  if (detail && (swi < vec_len (am->output_lc_index_by_sw_if_index)))
3249  {
3250  vlib_cli_output (vm, " output lookup context index: %d",
3252  }
3253  }
3254 
3255 }
3256 
3257 
3258 static clib_error_t *
3260  unformat_input_t * input,
3261  vlib_cli_command_t * cmd)
3262 {
3263  clib_error_t *error = 0;
3264  u64 five_tuple[6] = { 0, 0, 0, 0, 0, 0 };
3265 
3266  if (unformat
3267  (input, "%llx %llx %llx %llx %llx %llx", &five_tuple[0], &five_tuple[1],
3268  &five_tuple[2], &five_tuple[3], &five_tuple[4], &five_tuple[5]))
3269  vlib_cli_output (vm, "5-tuple structure decode: %U\n\n",
3270  format_acl_plugin_5tuple, five_tuple);
3271  else
3272  error = clib_error_return (0, "expecting 6 hex integers");
3273  return error;
3274 }
3275 
3276 
3277 static clib_error_t *
3280  input, vlib_cli_command_t * cmd)
3281 {
3282  clib_error_t *error = 0;
3283  acl_main_t *am = &acl_main;
3284 
3285  u32 sw_if_index = ~0;
3286  (void) unformat (input, "sw_if_index %u", &sw_if_index);
3287  int show_acl = unformat (input, "acl");
3288  int detail = unformat (input, "detail");
3289 
3290  acl_plugin_show_interface (am, sw_if_index, show_acl, detail);
3291  return error;
3292 }
3293 
3294 static clib_error_t *
3296  unformat_input_t * input,
3297  vlib_cli_command_t * cmd)
3298 {
3299  clib_error_t *error = 0;
3300  acl_main_t *am = &acl_main;
3301 
3302  vlib_cli_output (vm, "ACL plugin main heap statistics:\n");
3303  if (am->acl_mheap)
3304  {
3305  vlib_cli_output (vm, " %U\n", format_mheap, am->acl_mheap, 1);
3306  }
3307  else
3308  {
3309  vlib_cli_output (vm, " Not initialized\n");
3310  }
3311  vlib_cli_output (vm, "ACL hash lookup support heap statistics:\n");
3312  if (am->hash_lookup_mheap)
3313  {
3314  vlib_cli_output (vm, " %U\n", format_mheap, am->hash_lookup_mheap, 1);
3315  }
3316  else
3317  {
3318  vlib_cli_output (vm, " Not initialized\n");
3319  }
3320  return error;
3321 }
3322 
3323 static void
3325  u32 show_session_thread_id,
3326  u32 show_session_session_index)
3327 {
3328  vlib_main_t *vm = am->vlib_main;
3329  u16 wk;
3331  vnet_sw_interface_t *swif;
3332  u64 now = clib_cpu_time_now ();
3333  u64 clocks_per_second = am->vlib_main->clib_time.clocks_per_second;
3334 
3335  {
3336  u64 n_adds = am->fa_session_total_adds;
3337  u64 n_dels = am->fa_session_total_dels;
3338  u64 n_deact = am->fa_session_total_deactivations;
3339  vlib_cli_output (vm, "Sessions total: add %lu - del %lu = %lu", n_adds,
3340  n_dels, n_adds - n_dels);
3341  vlib_cli_output (vm, "Sessions active: add %lu - deact %lu = %lu", n_adds,
3342  n_deact, n_adds - n_deact);
3343  vlib_cli_output (vm, "Sessions being purged: deact %lu - del %lu = %lu",
3344  n_deact, n_dels, n_deact - n_dels);
3345  }
3346  vlib_cli_output (vm, "now: %lu clocks per second: %lu", now,
3347  clocks_per_second);
3348  vlib_cli_output (vm, "\n\nPer-thread data:");
3349  for (wk = 0; wk < vec_len (am->per_worker_data); wk++)
3350  {
3352  vlib_cli_output (vm, "Thread #%d:", wk);
3353  if (show_session_thread_id == wk
3354  && show_session_session_index < pool_len (pw->fa_sessions_pool))
3355  {
3356  vlib_cli_output (vm, " session index %u:",
3357  show_session_session_index);
3358  fa_session_t *sess =
3359  pw->fa_sessions_pool + show_session_session_index;
3360  u64 *m = (u64 *) & sess->info;
3361  vlib_cli_output (vm,
3362  " info: %016llx %016llx %016llx %016llx %016llx %016llx",
3363  m[0], m[1], m[2], m[3], m[4], m[5]);
3364  vlib_cli_output (vm, " sw_if_index: %u", sess->sw_if_index);
3365  vlib_cli_output (vm, " tcp_flags_seen: %x",
3366  sess->tcp_flags_seen.as_u16);
3367  vlib_cli_output (vm, " last active time: %lu",
3368  sess->last_active_time);
3369  vlib_cli_output (vm, " thread index: %u", sess->thread_index);
3370  vlib_cli_output (vm, " link enqueue time: %lu",
3371  sess->link_enqueue_time);
3372  vlib_cli_output (vm, " link next index: %u",
3373  sess->link_next_idx);
3374  vlib_cli_output (vm, " link prev index: %u",
3375  sess->link_prev_idx);
3376  vlib_cli_output (vm, " link list id: %u", sess->link_list_id);
3377  }
3378  vlib_cli_output (vm, " connection add/del stats:", wk);
3379  /* *INDENT-OFF* */
3380  pool_foreach (swif, im->sw_interfaces,
3381  ({
3382  u32 sw_if_index = swif->sw_if_index;
3383  u64 n_adds =
3384  (sw_if_index < vec_len (pw->fa_session_adds_by_sw_if_index) ?
3385  pw->fa_session_adds_by_sw_if_index[sw_if_index] :
3386  0);
3387  u64 n_dels =
3388  (sw_if_index < vec_len (pw->fa_session_dels_by_sw_if_index) ?
3389  pw->fa_session_dels_by_sw_if_index[sw_if_index] :
3390  0);
3391  u64 n_epoch_changes =
3392  (sw_if_index < vec_len (pw->fa_session_epoch_change_by_sw_if_index) ?
3393  pw->fa_session_epoch_change_by_sw_if_index[sw_if_index] :
3394  0);
3395  vlib_cli_output (vm,
3396  " sw_if_index %d: add %lu - del %lu = %lu; epoch chg: %lu",
3397  sw_if_index,
3398  n_adds,
3399  n_dels,
3400  n_adds -
3401  n_dels,
3402  n_epoch_changes);
3403  }));
3404  /* *INDENT-ON* */
3405 
3406  vlib_cli_output (vm, " connection timeout type lists:", wk);
3407  u8 tt = 0;
3408  for (tt = 0; tt < ACL_N_TIMEOUTS; tt++)
3409  {
3410  u32 head_session_index = pw->fa_conn_list_head[tt];
3411  vlib_cli_output (vm, " fa_conn_list_head[%d]: %d", tt,
3412  head_session_index);
3413  if (~0 != head_session_index)
3414  {
3415  fa_session_t *sess = pw->fa_sessions_pool + head_session_index;
3416  vlib_cli_output (vm, " last active time: %lu",
3417  sess->last_active_time);
3418  vlib_cli_output (vm, " link enqueue time: %lu",
3419  sess->link_enqueue_time);
3420  }
3421  }
3422 
3423  vlib_cli_output (vm, " Next expiry time: %lu", pw->next_expiry_time);
3424  vlib_cli_output (vm, " Requeue until time: %lu",
3425  pw->requeue_until_time);
3426  vlib_cli_output (vm, " Current time wait interval: %lu",
3428  vlib_cli_output (vm, " Count of deleted sessions: %lu",
3429  pw->cnt_deleted_sessions);
3430  vlib_cli_output (vm, " Delete already deleted: %lu",
3432  vlib_cli_output (vm, " Session timers restarted: %lu",
3434  vlib_cli_output (vm, " Swipe until this time: %lu",
3435  pw->swipe_end_time);
3436  vlib_cli_output (vm, " sw_if_index serviced bitmap: %U",
3437  format_bitmap_hex, pw->serviced_sw_if_index_bitmap);
3438  vlib_cli_output (vm, " pending clear intfc bitmap : %U",
3439  format_bitmap_hex,
3441  vlib_cli_output (vm, " clear in progress: %u", pw->clear_in_process);
3442  vlib_cli_output (vm, " interrupt is pending: %d",
3443  pw->interrupt_is_pending);
3444  vlib_cli_output (vm, " interrupt is needed: %d",
3445  pw->interrupt_is_needed);
3446  vlib_cli_output (vm, " interrupt is unwanted: %d",
3447  pw->interrupt_is_unwanted);
3448  vlib_cli_output (vm, " interrupt generation: %d",
3449  pw->interrupt_generation);
3450  vlib_cli_output (vm, " received session change requests: %d",
3452  vlib_cli_output (vm, " sent session change requests: %d",
3454  }
3455  vlib_cli_output (vm, "\n\nConn cleaner thread counters:");
3456 #define _(cnt, desc) vlib_cli_output(vm, " %20lu: %s", am->cnt, desc);
3458 #undef _
3459  vlib_cli_output (vm, "Interrupt generation: %d",
3461  vlib_cli_output (vm,
3462  "Sessions per interval: min %lu max %lu increment: %f ms current: %f ms",
3465  am->fa_cleaner_wait_time_increment * 1000.0,
3467  1000.0 / (f64) vm->clib_time.clocks_per_second);
3468  vlib_cli_output (vm, "Reclassify sessions: %d", am->reclassify_sessions);
3469 }
3470 
3471 static clib_error_t *
3473  unformat_input_t * input,
3474  vlib_cli_command_t * cmd)
3475 {
3476  clib_error_t *error = 0;
3477  acl_main_t *am = &acl_main;
3478 
3479  u32 show_bihash_verbose = 0;
3480  u32 show_session_thread_id = ~0;
3481  u32 show_session_session_index = ~0;
3482  (void) unformat (input, "thread %u index %u", &show_session_thread_id,
3483  &show_session_session_index);
3484  (void) unformat (input, "verbose %u", &show_bihash_verbose);
3485 
3486  acl_plugin_show_sessions (am, show_session_thread_id,
3487  show_session_session_index);
3488  show_fa_sessions_hash (vm, show_bihash_verbose);
3489  return error;
3490 }
3491 
3492 static clib_error_t *
3494  unformat_input_t * input,
3495  vlib_cli_command_t * cmd)
3496 {
3497  clib_error_t *error = 0;
3498 
3499  u32 acl_index = ~0;
3500  u32 lc_index = ~0;
3501  int show_acl_hash_info = 0;
3502  int show_applied_info = 0;
3503  int show_mask_type = 0;
3504  int show_bihash = 0;
3505  u32 show_bihash_verbose = 0;
3506 
3507  if (unformat (input, "acl"))
3508  {
3509  show_acl_hash_info = 1;
3510  /* mask-type is handy to see as well right there */
3511  show_mask_type = 1;
3512  unformat (input, "index %u", &acl_index);
3513  }
3514  else if (unformat (input, "applied"))
3515  {
3516  show_applied_info = 1;
3517  unformat (input, "lc_index %u", &lc_index);
3518  }
3519  else if (unformat (input, "mask"))
3520  {
3521  show_mask_type = 1;
3522  }
3523  else if (unformat (input, "hash"))
3524  {
3525  show_bihash = 1;
3526  unformat (input, "verbose %u", &show_bihash_verbose);
3527  }
3528 
3529  if (!
3530  (show_mask_type || show_acl_hash_info || show_applied_info
3531  || show_bihash))
3532  {
3533  /* if no qualifiers specified, show all */
3534  show_mask_type = 1;
3535  show_acl_hash_info = 1;
3536  show_applied_info = 1;
3537  show_bihash = 1;
3538  }
3539  vlib_cli_output (vm, "Stats counters enabled for interface ACLs: %d",
3541  if (show_mask_type)
3543  if (show_acl_hash_info)
3545  if (show_applied_info)
3547  if (show_bihash)
3548  acl_plugin_show_tables_bihash (show_bihash_verbose);
3549 
3550  return error;
3551 }
3552 
3553 static clib_error_t *
3555  unformat_input_t * input, vlib_cli_command_t * cmd)
3556 {
3557  clib_error_t *error = 0;
3558  acl_main_t *am = &acl_main;
3561  return error;
3562 }
3563 
3564  /* *INDENT-OFF* */
3565 VLIB_CLI_COMMAND (aclplugin_set_command, static) = {
3566  .path = "set acl-plugin",
3567  .short_help = "set acl-plugin session timeout {{udp idle}|tcp {idle|transient}} <seconds>",
3568  .function = acl_set_aclplugin_fn,
3569 };
3570 
3571 VLIB_CLI_COMMAND (aclplugin_show_acl_command, static) = {
3572  .path = "show acl-plugin acl",
3573  .short_help = "show acl-plugin acl [index N]",
3574  .function = acl_show_aclplugin_acl_fn,
3575 };
3576 
3577 VLIB_CLI_COMMAND (aclplugin_show_lookup_context_command, static) = {
3578  .path = "show acl-plugin lookup context",
3579  .short_help = "show acl-plugin lookup context [index N]",
3581 };
3582 
3583 VLIB_CLI_COMMAND (aclplugin_show_lookup_user_command, static) = {
3584  .path = "show acl-plugin lookup user",
3585  .short_help = "show acl-plugin lookup user [index N]",
3587 };
3588 
3589 VLIB_CLI_COMMAND (aclplugin_show_decode_5tuple_command, static) = {
3590  .path = "show acl-plugin decode 5tuple",
3591  .short_help = "show acl-plugin decode 5tuple XXXX XXXX XXXX XXXX XXXX XXXX",
3593 };
3594 
3595 VLIB_CLI_COMMAND (aclplugin_show_interface_command, static) = {
3596  .path = "show acl-plugin interface",
3597  .short_help = "show acl-plugin interface [sw_if_index N] [acl]",
3598  .function = acl_show_aclplugin_interface_fn,
3599 };
3600 
3601 VLIB_CLI_COMMAND (aclplugin_show_memory_command, static) = {
3602  .path = "show acl-plugin memory",
3603  .short_help = "show acl-plugin memory",
3604  .function = acl_show_aclplugin_memory_fn,
3605 };
3606 
3607 VLIB_CLI_COMMAND (aclplugin_show_sessions_command, static) = {
3608  .path = "show acl-plugin sessions",
3609  .short_help = "show acl-plugin sessions",
3610  .function = acl_show_aclplugin_sessions_fn,
3611 };
3612 
3613 VLIB_CLI_COMMAND (aclplugin_show_tables_command, static) = {
3614  .path = "show acl-plugin tables",
3615  .short_help = "show acl-plugin tables [ acl [index N] | applied [ lc_index N ] | mask | hash [verbose N] ]",
3616  .function = acl_show_aclplugin_tables_fn,
3617 };
3618 
3619 VLIB_CLI_COMMAND (aclplugin_show_macip_acl_command, static) = {
3620  .path = "show acl-plugin macip acl",
3621  .short_help = "show acl-plugin macip acl [index N]",
3622  .function = acl_show_aclplugin_macip_acl_fn,
3623 };
3624 
3625 VLIB_CLI_COMMAND (aclplugin_show_macip_interface_command, static) = {
3626  .path = "show acl-plugin macip interface",
3627  .short_help = "show acl-plugin macip interface",
3629 };
3630 
3631 VLIB_CLI_COMMAND (aclplugin_clear_command, static) = {
3632  .path = "clear acl-plugin sessions",
3633  .short_help = "clear acl-plugin sessions",
3634  .function = acl_clear_aclplugin_fn,
3635 };
3636 
3637 /*?
3638  * [un]Apply an ACL to an interface.
3639  * The ACL is applied in a given direction, either input or output.
3640  * The ACL being applied must already exist.
3641  *
3642  * @cliexpar
3643  * <b><em> set acl-plugin interface <input|output> acl <index> [del] </b></em>
3644  * @cliexend
3645  ?*/
3646 VLIB_CLI_COMMAND (aclplugin_set_interface_command, static) = {
3647  .path = "set acl-plugin interface",
3648  .short_help = "set acl-plugin interface <interface> <input|output> <acl INDEX> [del] ",
3649  .function = acl_set_aclplugin_interface_fn,
3650 };
3651 
3652 /*?
3653  * Create an Access Control List (ACL)
3654  * an ACL is composed of more than one Access control element (ACE). Multiple
3655  * ACEs can be specified with this command using a comma separated list.
3656  *
3657  * Each ACE describes a tuple of src+dst IP prefix, ip protocol, src+dst port ranges.
3658  * (the ACL plugin also support ICMP types/codes instead of UDP/TCP ports, but
3659  * this CLI does not).
3660  *
3661  * An ACL can optionally be assigned a 'tag' - which is an identifier understood
3662  * by the client. VPP does not examine it in any way.
3663  *
3664  * @cliexpar
3665  * <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>
3666  * @cliexend
3667  ?*/
3668 VLIB_CLI_COMMAND (aclplugin_set_acl_command, static) = {
3669  .path = "set acl-plugin acl",
3670  .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}",
3671  .function = acl_set_aclplugin_acl_fn,
3672 };
3673 /* *INDENT-ON* */
3674 
3675 static clib_error_t *
3677 {
3678  acl_main_t *am = &acl_main;
3679  u32 conn_table_hash_buckets;
3680  uword conn_table_hash_memory_size;
3681  u32 conn_table_max_entries;
3682  uword main_heap_size;
3683  uword hash_heap_size;
3684  u32 hash_lookup_hash_buckets;
3685  uword hash_lookup_hash_memory;
3686  u32 reclassify_sessions;
3687  u32 use_tuple_merge;
3688  u32 tuple_merge_split_threshold;
3689 
3690  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3691  {
3692  if (unformat
3693  (input, "connection hash buckets %d", &conn_table_hash_buckets))
3694  am->fa_conn_table_hash_num_buckets = conn_table_hash_buckets;
3695  else
3696  if (unformat
3697  (input, "connection hash memory %U", unformat_memory_size,
3698  &conn_table_hash_memory_size))
3699  am->fa_conn_table_hash_memory_size = conn_table_hash_memory_size;
3700  else if (unformat (input, "connection count max %d",
3701  &conn_table_max_entries))
3702  am->fa_conn_table_max_entries = conn_table_max_entries;
3703  else
3704  if (unformat
3705  (input, "main heap size %U", unformat_memory_size,
3706  &main_heap_size))
3707  am->acl_mheap_size = main_heap_size;
3708  else
3709  if (unformat
3710  (input, "hash lookup heap size %U", unformat_memory_size,
3711  &hash_heap_size))
3712  am->hash_lookup_mheap_size = hash_heap_size;
3713  else if (unformat (input, "hash lookup hash buckets %d",
3714  &hash_lookup_hash_buckets))
3715  am->hash_lookup_hash_buckets = hash_lookup_hash_buckets;
3716  else
3717  if (unformat
3718  (input, "hash lookup hash memory %U", unformat_memory_size,
3719  &hash_lookup_hash_memory))
3720  am->hash_lookup_hash_memory = hash_lookup_hash_memory;
3721  else if (unformat (input, "use tuple merge %d", &use_tuple_merge))
3722  am->use_tuple_merge = use_tuple_merge;
3723  else
3724  if (unformat
3725  (input, "tuple merge split threshold %d",
3726  &tuple_merge_split_threshold))
3727  am->tuple_merge_split_threshold = tuple_merge_split_threshold;
3728 
3729  else if (unformat (input, "reclassify sessions %d",
3730  &reclassify_sessions))
3731  am->reclassify_sessions = reclassify_sessions;
3732 
3733  else
3734  return clib_error_return (0, "unknown input '%U'",
3735  format_unformat_error, input);
3736  }
3737  return 0;
3738 }
3739 
3740 VLIB_CONFIG_FUNCTION (acl_plugin_config, "acl-plugin");
3741 
3742 /* Set up the API message handling tables */
3743 #include <vnet/format_fns.h>
3744 #include <acl/acl.api.c>
3745 
3746 static clib_error_t *
3748 {
3749  acl_main_t *am = &acl_main;
3750  clib_error_t *error = 0;
3751  clib_memset (am, 0, sizeof (*am));
3752  am->vlib_main = vm;
3753  am->vnet_main = vnet_get_main ();
3754  am->log_default = vlib_log_register_class ("acl_plugin", 0);
3755 
3756  /* Ask for a correctly-sized block of API message decode slots */
3758 
3759  error = acl_plugin_exports_init (&acl_plugin);
3760 
3761  if (error)
3762  return error;
3763 
3764  am->acl_mheap_size = 0; /* auto size when initializing */
3766 
3769 
3776 
3782  am->reclassify_sessions = 0;
3784 
3791 
3792  vec_validate (am->per_worker_data, tm->n_vlib_mains - 1);
3793  {
3794  u16 wk;
3795  for (wk = 0; wk < vec_len (am->per_worker_data); wk++)
3796  {
3798  if (tm->n_vlib_mains > 1)
3799  {
3801  }
3802  vec_validate (pw->expired,
3803  ACL_N_TIMEOUTS *
3805  _vec_len (pw->expired) = 0;
3811  ACL_N_TIMEOUTS - 1, ~0ULL);
3812  }
3813  }
3814 
3815  am->fa_cleaner_cnt_delete_by_sw_index = 0;
3816  am->fa_cleaner_cnt_delete_by_sw_index_ok = 0;
3817  am->fa_cleaner_cnt_unknown_event = 0;
3818  am->fa_cleaner_cnt_timer_restarted = 0;
3819  am->fa_cleaner_cnt_wait_with_timeout = 0;
3820 
3821 
3822 #define _(N, v, s) am->fa_ipv6_known_eh_bitmap = clib_bitmap_set(am->fa_ipv6_known_eh_bitmap, v, 1);
3824 #undef _
3826 
3827  /* use the new fancy hash-based matching */
3828  am->use_hash_acl_matching = 1;
3829  /* use tuplemerge by default */
3830  am->use_tuple_merge = 1;
3831  /* Set the default threshold */
3833 
3834  am->interface_acl_user_id =
3835  acl_plugin.register_user_module ("interface ACL", "sw_if_index",
3836  "is_input");
3837 
3840  am->acl_counter_lock[0] = 0; /* should be no need */
3841 
3842  return error;
3843 }
3844 
3846 
3847 
3848 /*
3849  * fd.io coding-style-patch-verification: ON
3850  *
3851  * Local Variables:
3852  * eval: (c-set-style "gnu")
3853  * End:
3854  */
static void vl_api_acl_stats_intf_counters_enable_t_handler(vl_api_acl_stats_intf_counters_enable_t *mp)
Definition: acl.c:1895
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:507
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:1736
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:2851
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:1804
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:3554
static int acl_set_skip_ipv6_eh(u32 eh, u32 value)
Definition: acl.c:2554
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:3160
static int verify_message_len(void *mp, u32 expected_len, char *where)
Definition: acl.c:1837
#define UDP_SESSION_IDLE_TIMEOUT_SEC
Definition: acl.h:40
static clib_error_t * acl_init(vlib_main_t *vm)
Definition: acl.c:3747
u32 acl_index
Definition: abf.api:58
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
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:56
static void vl_api_acl_add_replace_t_handler(vl_api_acl_add_replace_t *mp)
Definition: acl.c:1854
static void vl_api_macip_acl_dump_t_handler(vl_api_macip_acl_dump_t *mp)
Definition: acl.c:2284
#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:3676
#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:2151
static void vl_api_acl_interface_etype_whitelist_dump_t_handler(vl_api_acl_interface_list_dump_t *mp)
Definition: acl.c:2496
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:590
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:1013
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
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:944
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:87
u32 dot1ad_table_index
Definition: acl.c:938
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
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:951
vl_api_interface_index_t sw_if_index
Definition: acl.api:164
u32 table_index
Definition: acl.c:935
#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:939
#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:2570
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
vl_api_interface_index_t sw_if_index
Definition: gre.api:53
#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:3132
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:3278
#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:932
u32 out_arp_dot1q_table_index
Definition: acl.c:946
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:1010
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:3259
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:2805
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:388
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:3295
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:3175
Details about a single MACIP ACL contents.
Definition: acl.api:428
static void acl_set_session_max_entries(u32 value)
Definition: acl.c:2547
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:934
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:2030
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:151
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
u64 size
Definition: vhost_user.h:150
#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:427
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:3493
#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:873
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:1998
vl_api_address_union_t src_address
Definition: ip_types.api:99
static int get_l3_src_offset(int is6)
Definition: acl.c:1002
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:1584
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:2437
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:2797
u64 * fa_conn_list_head_expiry_time
Definition: fa_node.h:181
vlib_main_t * vm
Definition: in2out_ed.c:1599
u32 out_arp_dot1ad_table_index
Definition: acl.c:947
#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:994
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:2407
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:973
static int macip_acl_del_list(u32 acl_list_index)
Definition: acl.c:1768
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:3093
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:143
u32 dot1q_table_index
Definition: acl.c:937
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:57
#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:943
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:152
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:55
vl_api_gbp_rule_t rules[n_rules]
Definition: gbp.api:315
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:3041
#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:1908
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:1699
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:689
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:2205
#define vec_validate_acl_rules(v, idx)
Definition: acl.c:2895
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:1036
static void acl_set_timeout_sec(int timeout_type, u32 value)
Definition: acl.c:2528
void * mheap_alloc_with_lock(void *memory, uword size, int locked)
Definition: mem_dlmalloc.c:491
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:1030
#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:2178
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:1611
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:2820
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:2117
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:818
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:891
u32 out_table_index
Definition: acl.c:942
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:2906
u32 arp_dot1ad_table_index
Definition: acl.c:940
static void vl_api_acl_del_t_handler(vl_api_acl_del_t *mp)
Definition: acl.c:1881
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:2237
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:3472
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:2346
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:2371
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:1053
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:858
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
static void vl_api_acl_interface_set_acl_list_t_handler(vl_api_acl_interface_set_acl_list_t *mp)
Definition: acl.c:1928
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:2597
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:829
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:3324
static void copy_acl_rule_to_api_rule(vl_api_acl_rule_t *api_rule, acl_rule_t *r)
Definition: acl.c:1979
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:3256
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:748
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:3077
#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:554
#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:3146
u32 out_dot1ad_table_index
Definition: acl.c:945
#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:2218
u32 arp_table_index
Definition: acl.c:936
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:2070
static void macip_destroy_classify_tables(acl_main_t *am, u32 macip_acl_index)
Definition: acl.c:1540
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:2317
foreach_fa_cleaner_counter vlib_main_t * vlib_main
Definition: acl.h:303