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