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