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