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