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