FD.io VPP  v18.01-8-g0eacf49
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 "hash_lookup.h"
55 
57 
58 #define REPLY_MSG_ID_BASE am->msg_id_base
60 
61 /* List of message types that this plugin understands */
62 
63 #define foreach_acl_plugin_api_msg \
64 _(ACL_PLUGIN_GET_VERSION, acl_plugin_get_version) \
65 _(ACL_PLUGIN_CONTROL_PING, acl_plugin_control_ping) \
66 _(ACL_ADD_REPLACE, acl_add_replace) \
67 _(ACL_DEL, acl_del) \
68 _(ACL_INTERFACE_ADD_DEL, acl_interface_add_del) \
69 _(ACL_INTERFACE_SET_ACL_LIST, acl_interface_set_acl_list) \
70 _(ACL_DUMP, acl_dump) \
71 _(ACL_INTERFACE_LIST_DUMP, acl_interface_list_dump) \
72 _(MACIP_ACL_ADD, macip_acl_add) \
73 _(MACIP_ACL_ADD_REPLACE, macip_acl_add_replace) \
74 _(MACIP_ACL_DEL, macip_acl_del) \
75 _(MACIP_ACL_INTERFACE_ADD_DEL, macip_acl_interface_add_del) \
76 _(MACIP_ACL_DUMP, macip_acl_dump) \
77 _(MACIP_ACL_INTERFACE_GET, macip_acl_interface_get) \
78 _(MACIP_ACL_INTERFACE_LIST_DUMP, macip_acl_interface_list_dump)
79 
80 
81 /* *INDENT-OFF* */
83  .version = VPP_BUILD_VER,
84  .description = "Access Control Lists",
85 };
86 /* *INDENT-ON* */
87 
88 
89 static void *
91 {
92  if (0 == am->acl_mheap)
93  {
94  am->acl_mheap = mheap_alloc (0 /* use VM */ , am->acl_mheap_size);
97  }
98  void *oldheap = clib_mem_set_heap (am->acl_mheap);
99  return oldheap;
100 }
101 
102 void
104 {
106  mheap_t *h = mheap_header (am->acl_mheap);
107  if (on)
108  {
111  mheap_validate (h);
112  }
113  else
114  {
115  h->flags &= ~MHEAP_FLAG_VALIDATE;
117  }
118 }
119 
120 void
122 {
124  mheap_t *h = mheap_header (am->acl_mheap);
125  if (on)
126  {
127  h->flags |= MHEAP_FLAG_TRACE;
128  }
129  else
130  {
131  h->flags &= ~MHEAP_FLAG_TRACE;
132  }
133 }
134 
135 static void
137 {
138  acl_main_t *am = &acl_main;
140  int msg_size = sizeof (*rmp);
142 
144  if (q == 0)
145  {
146  return;
147  }
148 
149  rmp = vl_msg_api_alloc (msg_size);
150  memset (rmp, 0, msg_size);
151  rmp->_vl_msg_id =
152  ntohs (VL_API_ACL_PLUGIN_GET_VERSION_REPLY + am->msg_id_base);
153  rmp->context = mp->context;
154  rmp->major = htonl (ACL_PLUGIN_VERSION_MAJOR);
155  rmp->minor = htonl (ACL_PLUGIN_VERSION_MINOR);
156 
157  vl_msg_api_send_shmem (q, (u8 *) & rmp);
158 }
159 
160 static void
162  mp)
163 {
165  acl_main_t *am = &acl_main;
166  int rv = 0;
167 
168  /* *INDENT-OFF* */
169  REPLY_MACRO2 (VL_API_ACL_PLUGIN_CONTROL_PING_REPLY,
170  ({
171  rmp->vpe_pid = ntohl (getpid ());
172  }));
173  /* *INDENT-ON* */
174 }
175 
176 static int
178  u32 * acl_list_index, u8 * tag)
179 {
180  acl_main_t *am = &acl_main;
181  acl_list_t *a;
182  acl_rule_t *r;
183  acl_rule_t *acl_new_rules = 0;
184  int i;
185 
186  if (*acl_list_index != ~0)
187  {
188  /* They supplied some number, let's see if this ACL exists */
189  if (pool_is_free_index (am->acls, *acl_list_index))
190  {
191  /* tried to replace a non-existent ACL, no point doing anything */
193  ("acl-plugin-error: Trying to replace nonexistent ACL %d (tag %s)",
194  *acl_list_index, tag);
195  return VNET_API_ERROR_NO_SUCH_ENTRY;
196  }
197  }
198  if (0 == count)
199  {
201  ("acl-plugin-warning: supplied no rules for ACL %d (tag %s)",
202  *acl_list_index, tag);
203  }
204 
205  void *oldheap = acl_set_heap (am);
206 
207  /* Create and populate the rules */
208  if (count > 0)
209  vec_validate (acl_new_rules, count - 1);
210 
211  for (i = 0; i < count; i++)
212  {
213  r = vec_elt_at_index (acl_new_rules, i);
214  memset (r, 0, sizeof (*r));
215  r->is_permit = rules[i].is_permit;
216  r->is_ipv6 = rules[i].is_ipv6;
217  if (r->is_ipv6)
218  {
219  memcpy (&r->src, rules[i].src_ip_addr, sizeof (r->src));
220  memcpy (&r->dst, rules[i].dst_ip_addr, sizeof (r->dst));
221  }
222  else
223  {
224  memcpy (&r->src.ip4, rules[i].src_ip_addr, sizeof (r->src.ip4));
225  memcpy (&r->dst.ip4, rules[i].dst_ip_addr, sizeof (r->dst.ip4));
226  }
227  r->src_prefixlen = rules[i].src_ip_prefix_len;
228  r->dst_prefixlen = rules[i].dst_ip_prefix_len;
229  r->proto = rules[i].proto;
230  r->src_port_or_type_first = ntohs (rules[i].srcport_or_icmptype_first);
231  r->src_port_or_type_last = ntohs (rules[i].srcport_or_icmptype_last);
232  r->dst_port_or_code_first = ntohs (rules[i].dstport_or_icmpcode_first);
233  r->dst_port_or_code_last = ntohs (rules[i].dstport_or_icmpcode_last);
234  r->tcp_flags_value = rules[i].tcp_flags_value;
235  r->tcp_flags_mask = rules[i].tcp_flags_mask;
236  }
237 
238  if (~0 == *acl_list_index)
239  {
240  /* Get ACL index */
242  memset (a, 0, sizeof (*a));
243  /* Will return the newly allocated ACL index */
244  *acl_list_index = a - am->acls;
245  }
246  else
247  {
248  a = am->acls + *acl_list_index;
249  hash_acl_delete (am, *acl_list_index);
250  /* Get rid of the old rules */
251  if (a->rules)
252  vec_free (a->rules);
253  }
254  a->rules = acl_new_rules;
255  a->count = count;
256  memcpy (a->tag, tag, sizeof (a->tag));
257  hash_acl_add (am, *acl_list_index);
258  clib_mem_set_heap (oldheap);
259  return 0;
260 }
261 
262 static int
263 acl_del_list (u32 acl_list_index)
264 {
265  acl_main_t *am = &acl_main;
266  acl_list_t *a;
267  int i, ii;
268  if (pool_is_free_index (am->acls, acl_list_index))
269  {
270  return VNET_API_ERROR_NO_SUCH_ENTRY;
271  }
272 
273  if (acl_list_index < vec_len (am->input_sw_if_index_vec_by_acl))
274  {
275  if (vec_len (vec_elt (am->input_sw_if_index_vec_by_acl, acl_list_index))
276  > 0)
277  {
278  /* ACL is applied somewhere inbound. Refuse to delete */
279  return VNET_API_ERROR_ACL_IN_USE_INBOUND;
280  }
281  }
282  if (acl_list_index < vec_len (am->output_sw_if_index_vec_by_acl))
283  {
284  if (vec_len
285  (vec_elt (am->output_sw_if_index_vec_by_acl, acl_list_index)) > 0)
286  {
287  /* ACL is applied somewhere outbound. Refuse to delete */
288  return VNET_API_ERROR_ACL_IN_USE_OUTBOUND;
289  }
290  }
291 
292  void *oldheap = acl_set_heap (am);
293  /* delete any references to the ACL */
294  for (i = 0; i < vec_len (am->output_acl_vec_by_sw_if_index); i++)
295  {
296  for (ii = 0; ii < vec_len (am->output_acl_vec_by_sw_if_index[i]);
297  /* see body */ )
298  {
299  if (acl_list_index == am->output_acl_vec_by_sw_if_index[i][ii])
300  {
302  }
303  else
304  {
305  ii++;
306  }
307  }
308  }
309  for (i = 0; i < vec_len (am->input_acl_vec_by_sw_if_index); i++)
310  {
311  for (ii = 0; ii < vec_len (am->input_acl_vec_by_sw_if_index[i]);
312  /* see body */ )
313  {
314  if (acl_list_index == am->input_acl_vec_by_sw_if_index[i][ii])
315  {
317  }
318  else
319  {
320  ii++;
321  }
322  }
323  }
324  /* delete the hash table data */
325 
326  hash_acl_delete (am, acl_list_index);
327  /* now we can delete the ACL itself */
328  a = pool_elt_at_index (am->acls, acl_list_index);
329  if (a->rules)
330  vec_free (a->rules);
331 
332  pool_put (am->acls, a);
333  clib_mem_set_heap (oldheap);
334  return 0;
335 }
336 
337 /* Some aids in ASCII graphing the content */
338 #define XX "\377"
339 #define __ "\000"
340 #define _(x)
341 #define v
342 /* *INDENT-OFF* */
343 
345  _(" dmac smac etype ")
346  _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v __ __ v
347  _(" v ihl totlen ")
348  _(0x0000)
349  __ __ __ __
350  _(" ident fl+fo ")
351  _(0x0004)
352  __ __ __ __
353  _(" ttl pr checksum ")
354  _(0x0008)
355  __ XX __ __
356  _(" src address ")
357  _(0x000C)
358  XX XX XX XX
359  _(" dst address ")
360  _(0x0010)
361  XX XX XX XX
362  _("L4 T/U sport dport ")
363  _(tcpudp)
364  XX XX XX XX
365  _(padpad)
366  __ __ __ __
367  _(padpad)
368  __ __ __ __
369  _(padeth)
370  __ __;
371 
373  _(" dmac smac etype ")
374  _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v __ __ v
375  _(" v tc + flow ")
376  _(0x0000) __ __ __ __
377  _(" plen nh hl ")
378  _(0x0004) __ __ XX __
379  _(" src address ")
380  _(0x0008) XX XX XX XX
381  _(0x000C) XX XX XX XX
382  _(0x0010) XX XX XX XX
383  _(0x0014) XX XX XX XX
384  _(" dst address ")
385  _(0x0018) XX XX XX XX
386  _(0x001C) XX XX XX XX
387  _(0x0020) XX XX XX XX
388  _(0x0024) XX XX XX XX
389  _("L4T/U sport dport ")
390  _(tcpudp) XX XX XX XX _(padpad) __ __ __ __ _(padeth) __ __;
391 
393  _(" dmac smac dot1q etype ")
394  _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v XX XX __ __ v XX XX v
395  _(padpad) __ __ __ __
396  _(padpad) __ __ __ __
397  _(padpad) __ __ __ __
398  _(padeth) __ __;
399 
401  _(" dmac smac dot1ad dot1q etype ")
402  _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v XX XX __ __ XX XX __ __ v XX XX v
403  _(padpad) __ __ __ __
404  _(padpad) __ __ __ __
405  _(padeth) __ __;
406 
407 /* *INDENT-ON* */
408 #undef XX
409 #undef __
410 #undef _
411 #undef v
412 
413 static int
415 {
416  u64 *p64 = (u64 *) p;
417  /* Be tolerant to null pointer */
418  if (0 == p)
419  return 0;
420 
421  while ((0ULL == *p64) && ((u8 *) p64 - p) < size)
422  {
423  p64++;
424  }
425  return (p64 - (u64 *) p) / 2;
426 }
427 
428 static int
430  u32 mask_len, u32 next_table_index,
431  u32 miss_next_index, u32 * table_index,
432  int is_add)
433 {
434  u32 nbuckets = 1;
435  u32 memory_size = 2 << 13;
436  u32 skip = count_skip (mask, mask_len);
437  u32 match = (mask_len / 16) - skip;
438  u8 *skip_mask_ptr = mask + 16 * skip;
439  u32 current_data_flag = 0;
440  int current_data_offset = 0;
441 
442  if (0 == match)
443  match = 1;
444  void *oldheap = clib_mem_set_heap (cm->vlib_main->heap_base);
445  int ret = vnet_classify_add_del_table (cm, skip_mask_ptr, nbuckets,
446  memory_size, skip, match,
447  next_table_index, miss_next_index,
448  table_index, current_data_flag,
449  current_data_offset, is_add,
450  1 /* delete_chain */ );
451  clib_mem_set_heap (oldheap);
452  return ret;
453 }
454 
455 static int
457  u32 mask_len, u32 next_table_index,
458  u32 miss_next_index, u32 * table_index,
459  int is_add)
460 {
461  u32 nbuckets = 32;
462  u32 memory_size = 2 << 22;
463  u32 skip = count_skip (mask, mask_len);
464  u32 match = (mask_len / 16) - skip;
465  u8 *skip_mask_ptr = mask + 16 * skip;
466  u32 current_data_flag = 0;
467  int current_data_offset = 0;
468 
469  if (0 == match)
470  match = 1;
471 
472  void *oldheap = clib_mem_set_heap (cm->vlib_main->heap_base);
473  int ret = vnet_classify_add_del_table (cm, skip_mask_ptr, nbuckets,
474  memory_size, skip, match,
475  next_table_index, miss_next_index,
476  table_index, current_data_flag,
477  current_data_offset, is_add,
478  1 /* delete_chain */ );
479  clib_mem_set_heap (oldheap);
480  return ret;
481 }
482 
483 static int
485 {
487  u32 ip4_table_index = ~0;
488  u32 ip6_table_index = ~0;
489  u32 dot1q_table_index = ~0;
490  u32 dot1ad_table_index = ~0;
491  void *oldheap = acl_set_heap (am);
492 
494  sw_if_index, ~0);
496  sw_if_index, ~0);
498  sw_if_index, ~0);
500  sw_if_index, ~0);
501 
502  /* switch to global heap while calling vnet_* functions */
503  clib_mem_set_heap (cm->vlib_main->heap_base);
504  vnet_l2_input_classify_enable_disable (sw_if_index, 0);
505 
506  if (am->acl_ip4_input_classify_table_by_sw_if_index[sw_if_index] != ~0)
507  {
508  ip4_table_index =
510  am->acl_ip4_input_classify_table_by_sw_if_index[sw_if_index] = ~0;
511  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
512  sizeof (ip4_5tuple_mask) - 1, ~0,
514  &ip4_table_index, 0);
515  }
516  if (am->acl_ip6_input_classify_table_by_sw_if_index[sw_if_index] != ~0)
517  {
518  ip6_table_index =
520  am->acl_ip6_input_classify_table_by_sw_if_index[sw_if_index] = ~0;
522  sizeof (ip6_5tuple_mask) - 1, ~0,
524  &ip6_table_index, 0);
525  }
526  if (am->acl_dot1q_input_classify_table_by_sw_if_index[sw_if_index] != ~0)
527  {
528  dot1q_table_index =
530  am->acl_dot1q_input_classify_table_by_sw_if_index[sw_if_index] = ~0;
532  sizeof (ip6_5tuple_mask) - 1, ~0,
533  ~0, &dot1q_table_index, 0);
534  }
535  if (am->acl_dot1ad_input_classify_table_by_sw_if_index[sw_if_index] != ~0)
536  {
537  dot1ad_table_index =
541  sizeof (dot1ad_5tuple_mask) - 1, ~0,
542  ~0, &dot1ad_table_index, 0);
543  }
544  clib_mem_set_heap (oldheap);
545  return 0;
546 }
547 
548 static int
550 {
552  u32 ip4_table_index = ~0;
553  u32 ip6_table_index = ~0;
554  u32 dot1q_table_index = ~0;
555  u32 dot1ad_table_index = ~0;
556  void *oldheap = acl_set_heap (am);
557 
559  sw_if_index, ~0);
561  sw_if_index, ~0);
563  sw_if_index, ~0);
566 
567  /* switch to global heap while calling vnet_* functions */
568  clib_mem_set_heap (cm->vlib_main->heap_base);
569 
571 
572  if (am->acl_ip4_output_classify_table_by_sw_if_index[sw_if_index] != ~0)
573  {
574  ip4_table_index =
576  am->acl_ip4_output_classify_table_by_sw_if_index[sw_if_index] = ~0;
577  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
578  sizeof (ip4_5tuple_mask) - 1, ~0,
580  &ip4_table_index, 0);
581  }
582  if (am->acl_ip6_output_classify_table_by_sw_if_index[sw_if_index] != ~0)
583  {
584  ip6_table_index =
586  am->acl_ip6_output_classify_table_by_sw_if_index[sw_if_index] = ~0;
588  sizeof (ip6_5tuple_mask) - 1, ~0,
590  &ip6_table_index, 0);
591  }
592  if (am->acl_dot1q_output_classify_table_by_sw_if_index[sw_if_index] != ~0)
593  {
594  dot1q_table_index =
598  sizeof (ip6_5tuple_mask) - 1, ~0,
599  ~0, &dot1q_table_index, 0);
600  }
601  if (am->acl_dot1ad_output_classify_table_by_sw_if_index[sw_if_index] != ~0)
602  {
603  dot1ad_table_index =
607  sizeof (dot1ad_5tuple_mask) - 1, ~0,
608  ~0, &dot1ad_table_index, 0);
609  }
610  clib_mem_set_heap (oldheap);
611  return 0;
612 }
613 
614 static void
615 acl_add_vlan_session (acl_main_t * am, u32 table_index, u8 is_output,
616  u8 is_dot1ad, u8 is_ip6)
617 {
619  u8 *match;
620  u32 next_acl;
621  u8 idx;
622  u8 session_idx;
623 
624  if (is_ip6)
625  {
626  next_acl =
627  (is_output) ? am->
628  l2_output_classify_next_acl_ip6 : am->l2_input_classify_next_acl_ip6;
629  }
630  else
631  {
632  next_acl =
633  (is_output) ? am->
634  l2_output_classify_next_acl_ip4 : am->l2_input_classify_next_acl_ip4;
635  }
636  match = (is_dot1ad) ? dot1ad_5tuple_mask : dot1q_5tuple_mask;
637  idx = (is_dot1ad) ? 20 : 16;
638  if (is_dot1ad)
639  {
640  /* 802.1ad ethertype */
641  match[12] = 0x88;
642  match[13] = 0xa8;
643  /* 802.1q ethertype */
644  match[16] = 0x81;
645  match[17] = 0x00;
646  }
647  else
648  {
649  /* 802.1q ethertype */
650  match[12] = 0x81;
651  match[13] = 0x00;
652  }
653 
654  /* add sessions to vlan tables per ethernet_type */
655  if (is_ip6)
656  {
657  match[idx] = 0x86;
658  match[idx + 1] = 0xdd;
659  session_idx = 1;
660  }
661  else
662  {
663  match[idx] = 0x08;
664  match[idx + 1] = 0x00;
665  session_idx = 0;
666  }
667  vnet_classify_add_del_session (cm, table_index, match, next_acl,
668  session_idx, 0, 0, 0, 1);
669  /* reset the mask back to being a mask */
670  match[idx] = 0xff;
671  match[idx + 1] = 0xff;
672  match[12] = 0xff;
673  match[13] = 0xff;
674  if (is_dot1ad)
675  {
676  match[16] = 0xff;
677  match[17] = 0xff;
678  }
679 }
680 
681 static int
683 {
685  u32 ip4_table_index = ~0;
686  u32 ip6_table_index = ~0;
687  u32 dot1q_table_index = ~0;
688  u32 dot1ad_table_index = ~0;
689  int rv;
690 
691  void *prevheap = clib_mem_set_heap (cm->vlib_main->heap_base);
692 
693  /* in case there were previous tables attached */
694  acl_unhook_l2_input_classify (am, sw_if_index);
695  rv =
696  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
697  sizeof (ip4_5tuple_mask) - 1, ~0,
699  &ip4_table_index, 1);
700  if (rv)
701  goto done;
702 
703  rv =
705  sizeof (ip6_5tuple_mask) - 1, ~0,
707  &ip6_table_index, 1);
708  if (rv)
709  {
710  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
711  sizeof (ip4_5tuple_mask) - 1, ~0,
713  &ip4_table_index, 0);
714  goto done;
715  }
716 
717  rv =
719  sizeof (dot1ad_5tuple_mask) - 1, ~0,
720  ~0, &dot1ad_table_index, 1);
721  rv =
723  sizeof (dot1q_5tuple_mask) - 1,
724  dot1ad_table_index, ~0,
725  &dot1q_table_index, 1);
726  if (rv)
727  {
729  sizeof (dot1ad_5tuple_mask) - 1, ~0,
730  ~0, &dot1ad_table_index, 0);
732  sizeof (ip6_5tuple_mask) - 1, ~0,
734  &ip6_table_index, 0);
735  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
736  sizeof (ip4_5tuple_mask) - 1, ~0,
738  &ip4_table_index, 0);
739  goto done;
740  }
741 
742  rv =
743  vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index,
744  ip6_table_index, dot1q_table_index);
745 
746  if (rv)
747  {
748  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
749  sizeof (ip4_5tuple_mask) - 1, ~0,
751  &ip4_table_index, 0);
753  sizeof (ip6_5tuple_mask) - 1, ~0,
755  &ip6_table_index, 0);
757  sizeof (dot1q_5tuple_mask) - 1, ~0,
758  ~0, &dot1q_table_index, 0);
760  sizeof (dot1ad_5tuple_mask) - 1, ~0,
761  ~0, &dot1ad_table_index, 0);
762  goto done;
763  }
764 
765  /* add sessions to vlan tables per ethernet_type */
766  acl_add_vlan_session (am, dot1q_table_index, 0, 0, 0);
767  acl_add_vlan_session (am, dot1q_table_index, 0, 0, 1);
768  acl_add_vlan_session (am, dot1ad_table_index, 0, 1, 0);
769  acl_add_vlan_session (am, dot1ad_table_index, 0, 1, 1);
770 
772  ip4_table_index;
774  ip6_table_index;
776  dot1q_table_index;
778  dot1ad_table_index;
779 
780  vnet_l2_input_classify_enable_disable (sw_if_index, 1);
781 done:
782  clib_mem_set_heap (prevheap);
783  return rv;
784 }
785 
786 static int
788 {
790  u32 ip4_table_index = ~0;
791  u32 ip6_table_index = ~0;
792  u32 dot1q_table_index = ~0;
793  u32 dot1ad_table_index = ~0;
794  int rv;
795 
796  void *prevheap = clib_mem_set_heap (cm->vlib_main->heap_base);
797 
798  /* in case there were previous tables attached */
799  acl_unhook_l2_output_classify (am, sw_if_index);
800  rv =
801  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
802  sizeof (ip4_5tuple_mask) - 1, ~0,
804  &ip4_table_index, 1);
805  if (rv)
806  goto done;
807  rv =
809  sizeof (ip6_5tuple_mask) - 1, ~0,
811  &ip6_table_index, 1);
812  if (rv)
813  {
814  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
815  sizeof (ip4_5tuple_mask) - 1, ~0,
817  &ip4_table_index, 0);
818  goto done;
819  }
820 
821  rv =
823  sizeof (dot1ad_5tuple_mask) - 1, ~0,
824  ~0, &dot1ad_table_index, 1);
825  rv =
827  sizeof (dot1q_5tuple_mask) - 1,
828  dot1ad_table_index, ~0,
829  &dot1q_table_index, 1);
830  if (rv)
831  {
833  sizeof (dot1ad_5tuple_mask) - 1, ~0,
834  ~0, &dot1ad_table_index, 0);
836  sizeof (ip6_5tuple_mask) - 1, ~0,
838  &ip6_table_index, 0);
839  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
840  sizeof (ip4_5tuple_mask) - 1, ~0,
842  &ip4_table_index, 0);
843  goto done;
844  }
845 
846  rv =
847  vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index,
848  ip6_table_index, dot1q_table_index);
849 
851  ("ACL enabling on interface sw_if_index %d, setting tables to the following: ip4: %d ip6: %d\n",
852  sw_if_index, ip4_table_index, ip6_table_index);
853  if (rv)
854  {
856  sizeof (ip6_5tuple_mask) - 1, ~0,
858  &ip6_table_index, 0);
859  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
860  sizeof (ip4_5tuple_mask) - 1, ~0,
862  &ip4_table_index, 0);
864  sizeof (dot1q_5tuple_mask) - 1, ~0,
865  ~0, &dot1q_table_index, 0);
867  sizeof (dot1ad_5tuple_mask) - 1, ~0,
868  ~0, &dot1ad_table_index, 0);
869  goto done;
870  }
871 
872  /* add sessions to vlan tables per ethernet_type */
873  acl_add_vlan_session (am, dot1q_table_index, 1, 0, 0);
874  acl_add_vlan_session (am, dot1q_table_index, 1, 0, 1);
875  acl_add_vlan_session (am, dot1ad_table_index, 1, 1, 0);
876  acl_add_vlan_session (am, dot1ad_table_index, 1, 1, 1);
877 
879  ip4_table_index;
881  ip6_table_index;
883  dot1q_table_index;
885  dot1ad_table_index;
886 
888 done:
889  clib_mem_set_heap (prevheap);
890  return rv;
891 }
892 
893 int
895  int enable_disable)
896 {
897  int rv;
898 
899  /* Utterly wrong? */
901  sw_if_index))
902  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
903 
904  acl_fa_enable_disable (sw_if_index, 1, enable_disable);
905 
906  if (enable_disable)
907  {
908  rv = acl_hook_l2_input_classify (am, sw_if_index);
909  }
910  else
911  {
912  rv = acl_unhook_l2_input_classify (am, sw_if_index);
913  }
914 
915  return rv;
916 }
917 
918 int
920  int enable_disable)
921 {
922  int rv;
923 
924  /* Utterly wrong? */
926  sw_if_index))
927  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
928 
929  acl_fa_enable_disable (sw_if_index, 0, enable_disable);
930 
931  if (enable_disable)
932  {
933  rv = acl_hook_l2_output_classify (am, sw_if_index);
934  }
935  else
936  {
937  rv = acl_unhook_l2_output_classify (am, sw_if_index);
938  }
939 
940  return rv;
941 }
942 
943 static int
944 acl_is_not_defined (acl_main_t * am, u32 acl_list_index)
945 {
946  return (pool_is_free_index (am->acls, acl_list_index));
947 }
948 
949 
950 static int
951 acl_interface_add_inout_acl (u32 sw_if_index, u8 is_input, u32 acl_list_index)
952 {
953  acl_main_t *am = &acl_main;
954  if (acl_is_not_defined (am, acl_list_index))
955  {
956  /* ACL is not defined. Can not apply */
957  return VNET_API_ERROR_NO_SUCH_ENTRY;
958  }
959  void *oldheap = acl_set_heap (am);
960 
961  if (is_input)
962  {
963  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
964 
965  u32 index = vec_search (am->input_acl_vec_by_sw_if_index[sw_if_index],
966  acl_list_index);
967  if (index < vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]))
968  {
970  ("ACL %d is already applied inbound on sw_if_index %d (index %d)",
971  acl_list_index, sw_if_index, index);
972  /* the entry is already there */
973  clib_mem_set_heap (oldheap);
974  return VNET_API_ERROR_ACL_IN_USE_INBOUND;
975  }
976  /* if there was no ACL applied before, enable the ACL processing */
977  if (vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]) == 0)
978  {
979  acl_interface_in_enable_disable (am, sw_if_index, 1);
980  }
981  vec_add (am->input_acl_vec_by_sw_if_index[sw_if_index], &acl_list_index,
982  1);
983  vec_validate (am->input_sw_if_index_vec_by_acl, acl_list_index);
984  vec_add (am->input_sw_if_index_vec_by_acl[acl_list_index], &sw_if_index,
985  1);
986  }
987  else
988  {
989  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
990 
991  u32 index = vec_search (am->output_acl_vec_by_sw_if_index[sw_if_index],
992  acl_list_index);
993  if (index < vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]))
994  {
996  ("ACL %d is already applied outbound on sw_if_index %d (index %d)",
997  acl_list_index, sw_if_index, index);
998  /* the entry is already there */
999  clib_mem_set_heap (oldheap);
1000  return VNET_API_ERROR_ACL_IN_USE_OUTBOUND;
1001  }
1002  /* if there was no ACL applied before, enable the ACL processing */
1003  if (vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]) == 0)
1004  {
1005  acl_interface_out_enable_disable (am, sw_if_index, 1);
1006  }
1007  vec_add (am->output_acl_vec_by_sw_if_index[sw_if_index],
1008  &acl_list_index, 1);
1009  vec_validate (am->output_sw_if_index_vec_by_acl, acl_list_index);
1010  vec_add (am->output_sw_if_index_vec_by_acl[acl_list_index],
1011  &sw_if_index, 1);
1012  }
1013  clib_mem_set_heap (oldheap);
1014  return 0;
1015 }
1016 
1017 
1018 static int
1019 acl_interface_del_inout_acl (u32 sw_if_index, u8 is_input, u32 acl_list_index)
1020 {
1021  acl_main_t *am = &acl_main;
1022  int i;
1023  int rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1024  void *oldheap = acl_set_heap (am);
1025  if (is_input)
1026  {
1027  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
1028  for (i = 0; i < vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]);
1029  i++)
1030  {
1031  if (acl_list_index ==
1032  am->input_acl_vec_by_sw_if_index[sw_if_index][i])
1033  {
1034  vec_del1 (am->input_acl_vec_by_sw_if_index[sw_if_index], i);
1035  rv = 0;
1036  break;
1037  }
1038  }
1039 
1040  if (acl_list_index < vec_len (am->input_sw_if_index_vec_by_acl))
1041  {
1042  u32 index =
1043  vec_search (am->input_sw_if_index_vec_by_acl[acl_list_index],
1044  sw_if_index);
1045  if (index <
1046  vec_len (am->input_sw_if_index_vec_by_acl[acl_list_index]))
1047  {
1048  hash_acl_unapply (am, sw_if_index, is_input, acl_list_index);
1049  vec_del1 (am->input_sw_if_index_vec_by_acl[acl_list_index],
1050  index);
1051  }
1052  }
1053 
1054  /* If there is no more ACLs applied on an interface, disable ACL processing */
1055  if (0 == vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]))
1056  {
1057  acl_interface_in_enable_disable (am, sw_if_index, 0);
1058  }
1059  }
1060  else
1061  {
1062  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
1063  for (i = 0;
1064  i < vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]); i++)
1065  {
1066  if (acl_list_index ==
1067  am->output_acl_vec_by_sw_if_index[sw_if_index][i])
1068  {
1069  vec_del1 (am->output_acl_vec_by_sw_if_index[sw_if_index], i);
1070  rv = 0;
1071  break;
1072  }
1073  }
1074 
1075  if (acl_list_index < vec_len (am->output_sw_if_index_vec_by_acl))
1076  {
1077  u32 index =
1078  vec_search (am->output_sw_if_index_vec_by_acl[acl_list_index],
1079  sw_if_index);
1080  if (index <
1081  vec_len (am->output_sw_if_index_vec_by_acl[acl_list_index]))
1082  {
1083  hash_acl_unapply (am, sw_if_index, is_input, acl_list_index);
1084  vec_del1 (am->output_sw_if_index_vec_by_acl[acl_list_index],
1085  index);
1086  }
1087  }
1088 
1089  /* If there is no more ACLs applied on an interface, disable ACL processing */
1090  if (0 == vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]))
1091  {
1092  acl_interface_out_enable_disable (am, sw_if_index, 0);
1093  }
1094  }
1095  clib_mem_set_heap (oldheap);
1096  return rv;
1097 }
1098 
1099 static void
1100 acl_interface_reset_inout_acls (u32 sw_if_index, u8 is_input)
1101 {
1102  acl_main_t *am = &acl_main;
1103  int i;
1104  void *oldheap = acl_set_heap (am);
1105  if (is_input)
1106  {
1107  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
1108  if (vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]) > 0)
1109  {
1110  acl_interface_in_enable_disable (am, sw_if_index, 0);
1111  }
1112 
1113  for (i = vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]) - 1;
1114  i >= 0; i--)
1115  {
1116  u32 acl_list_index =
1117  am->input_acl_vec_by_sw_if_index[sw_if_index][i];
1118  hash_acl_unapply (am, sw_if_index, is_input, acl_list_index);
1119  if (acl_list_index < vec_len (am->input_sw_if_index_vec_by_acl))
1120  {
1121  u32 index =
1122  vec_search (am->input_sw_if_index_vec_by_acl[acl_list_index],
1123  sw_if_index);
1124  if (index <
1125  vec_len (am->input_sw_if_index_vec_by_acl[acl_list_index]))
1126  {
1127  vec_del1 (am->input_sw_if_index_vec_by_acl[acl_list_index],
1128  index);
1129  }
1130  }
1131  }
1132 
1134  }
1135  else
1136  {
1137  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
1138  if (vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]) > 0)
1139  {
1140  acl_interface_out_enable_disable (am, sw_if_index, 0);
1141  }
1142 
1143  for (i = vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]) - 1;
1144  i >= 0; i--)
1145  {
1146  u32 acl_list_index =
1147  am->output_acl_vec_by_sw_if_index[sw_if_index][i];
1148  hash_acl_unapply (am, sw_if_index, is_input, acl_list_index);
1149  if (acl_list_index < vec_len (am->output_sw_if_index_vec_by_acl))
1150  {
1151  u32 index =
1152  vec_search (am->output_sw_if_index_vec_by_acl[acl_list_index],
1153  sw_if_index);
1154  if (index <
1155  vec_len (am->output_sw_if_index_vec_by_acl[acl_list_index]))
1156  {
1157  vec_del1 (am->output_sw_if_index_vec_by_acl[acl_list_index],
1158  index);
1159  }
1160  }
1161  }
1162 
1164  }
1165  clib_mem_set_heap (oldheap);
1166 }
1167 
1168 static int
1169 acl_interface_add_del_inout_acl (u32 sw_if_index, u8 is_add, u8 is_input,
1170  u32 acl_list_index)
1171 {
1172  int rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1173  acl_main_t *am = &acl_main;
1174  if (is_add)
1175  {
1176  rv =
1177  acl_interface_add_inout_acl (sw_if_index, is_input, acl_list_index);
1178  if (rv == 0)
1179  {
1180  hash_acl_apply (am, sw_if_index, is_input, acl_list_index);
1181  }
1182  }
1183  else
1184  {
1185  hash_acl_unapply (am, sw_if_index, is_input, acl_list_index);
1186  rv =
1187  acl_interface_del_inout_acl (sw_if_index, is_input, acl_list_index);
1188  }
1189  return rv;
1190 }
1191 
1192 
1193 typedef struct
1194 {
1196  u8 mac_mask[6];
1204 
1205 static u32
1206 macip_find_match_type (macip_match_type_t * mv, u8 * mac_mask, u8 prefix_len,
1207  u8 is_ipv6)
1208 {
1209  u32 i;
1210  if (mv)
1211  {
1212  for (i = 0; i < vec_len (mv); i++)
1213  {
1214  if ((mv[i].prefix_len == prefix_len) && (mv[i].is_ipv6 == is_ipv6)
1215  && (0 == memcmp (mv[i].mac_mask, mac_mask, 6)))
1216  {
1217  return i;
1218  }
1219  }
1220  }
1221  return ~0;
1222 }
1223 
1224 
1225 /* Get metric used to sort match types.
1226  The more specific and the more often seen - the bigger the metric */
1227 static int
1229 {
1230  unsigned int mac_bits_set = 0;
1231  unsigned int mac_byte;
1232  int i;
1233  for (i = 0; i < 6; i++)
1234  {
1235  mac_byte = m->mac_mask[i];
1236  for (; mac_byte; mac_byte >>= 1)
1237  mac_bits_set += mac_byte & 1;
1238  }
1239  /*
1240  * Attempt to place the more specific and the more used rules on top.
1241  * There are obvious caveat corner cases to this, but they do not
1242  * seem to be sensible in real world (e.g. specific IPv4 with wildcard MAC
1243  * going with a wildcard IPv4 with a specific MAC).
1244  */
1245  return m->prefix_len + mac_bits_set + m->is_ipv6 + 10 * m->count;
1246 }
1247 
1248 static int
1250 {
1251  /* Ascending sort based on the metric values */
1252  return match_type_metric (m1) - match_type_metric (m2);
1253 }
1254 
1255 /* Get the offset of L3 source within ethernet packet */
1256 static int
1258 {
1259  if (is6)
1260  return (sizeof (ethernet_header_t) +
1261  offsetof (ip6_header_t, src_address));
1262  else
1263  return (sizeof (ethernet_header_t) +
1264  offsetof (ip4_header_t, src_address));
1265 }
1266 
1267 static int
1269 {
1270  macip_match_type_t *mvec = NULL;
1271  macip_match_type_t *mt;
1272  macip_acl_list_t *a = pool_elt_at_index (am->macip_acls, macip_acl_index);
1273  int i;
1274  u32 match_type_index;
1275  u32 last_table;
1276  u8 mask[5 * 16];
1278 
1279  /* Count the number of different types of rules */
1280  for (i = 0; i < a->count; i++)
1281  {
1282  if (~0 ==
1283  (match_type_index =
1285  a->rules[i].src_prefixlen,
1286  a->rules[i].is_ipv6)))
1287  {
1288  match_type_index = vec_len (mvec);
1289  vec_validate (mvec, match_type_index);
1290  memcpy (mvec[match_type_index].mac_mask,
1291  a->rules[i].src_mac_mask, 6);
1292  mvec[match_type_index].prefix_len = a->rules[i].src_prefixlen;
1293  mvec[match_type_index].is_ipv6 = a->rules[i].is_ipv6;
1294  mvec[match_type_index].table_index = ~0;
1295  mvec[match_type_index].dot1q_table_index = ~0;
1296  mvec[match_type_index].dot1ad_table_index = ~0;
1297  }
1298  mvec[match_type_index].count++;
1299  }
1300  /* Put the most frequently used tables last in the list so we can create classifier tables in reverse order */
1302  /* Create the classifier tables */
1303  last_table = ~0;
1304  /* First add ARP tables */
1305  vec_foreach (mt, mvec)
1306  {
1307  int mask_len;
1308  int is6 = mt->is_ipv6;
1309 
1310  mt->arp_table_index = ~0;
1311  if (!is6)
1312  {
1313  memset (mask, 0, sizeof (mask));
1314  memcpy (&mask[6], mt->mac_mask, 6);
1315  memset (&mask[12], 0xff, 2); /* ethernet protocol */
1316  memcpy (&mask[14 + 8], mt->mac_mask, 6);
1317 
1318  for (i = 0; i < (mt->prefix_len / 8); i++)
1319  mask[14 + 14 + i] = 0xff;
1320  if (mt->prefix_len % 8)
1321  mask[14 + 14 + (mt->prefix_len / 8)] =
1322  0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
1323 
1324  mask_len = ((14 + 14 + ((mt->prefix_len + 7) / 8) +
1325  (sizeof (u32x4) - 1)) / sizeof (u32x4)) * sizeof (u32x4);
1326  acl_classify_add_del_table_small (cm, mask, mask_len, last_table,
1327  (~0 == last_table) ? 0 : ~0,
1328  &mt->arp_table_index, 1);
1329  last_table = mt->arp_table_index;
1330  }
1331  }
1332  /* Now add IP[46] tables */
1333  vec_foreach (mt, mvec)
1334  {
1335  int mask_len;
1336  int is6 = mt->is_ipv6;
1337  int l3_src_offs = get_l3_src_offset (is6);
1338  int tags;
1339  u32 *last_tag_table;
1340 
1341  /*
1342  * create chained tables for VLAN (no-tags, dot1q and dot1ad) packets
1343  */
1344  l3_src_offs += 8;
1345  for (tags = 2; tags >= 0; tags--)
1346  {
1347  memset (mask, 0, sizeof (mask));
1348  memcpy (&mask[6], mt->mac_mask, 6);
1349  switch (tags)
1350  {
1351  case 0:
1352  default:
1353  memset (&mask[12], 0xff, 2); /* ethernet protocol */
1354  last_tag_table = &mt->table_index;
1355  break;
1356  case 1:
1357  memset (&mask[12], 0xff, 2); /* VLAN tag1 */
1358  memset (&mask[16], 0xff, 2); /* ethernet protocol */
1359  last_tag_table = &mt->dot1q_table_index;
1360  break;
1361  case 2:
1362  memset (&mask[12], 0xff, 2); /* VLAN tag1 */
1363  memset (&mask[16], 0xff, 2); /* VLAN tag2 */
1364  memset (&mask[20], 0xff, 2); /* ethernet protocol */
1365  last_tag_table = &mt->dot1ad_table_index;
1366  break;
1367  }
1368  for (i = 0; i < (mt->prefix_len / 8); i++)
1369  {
1370  mask[l3_src_offs + i] = 0xff;
1371  }
1372  if (mt->prefix_len % 8)
1373  {
1374  mask[l3_src_offs + (mt->prefix_len / 8)] =
1375  0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
1376  }
1377  /*
1378  * Round-up the number of bytes needed to store the prefix,
1379  * and round up the number of vectors too
1380  */
1381  mask_len = ((l3_src_offs + ((mt->prefix_len + 7) / 8) +
1382  (sizeof (u32x4) - 1)) / sizeof (u32x4)) * sizeof (u32x4);
1383  acl_classify_add_del_table_small (cm, mask, mask_len, last_table,
1384  (~0 == last_table) ? 0 : ~0,
1385  last_tag_table, 1);
1386  last_table = *last_tag_table;
1387 
1388  memset (&mask[12], 0, sizeof (mask) - 12);
1389  l3_src_offs -= 4;
1390  }
1391  }
1392  a->ip4_table_index = last_table;
1393  a->ip6_table_index = last_table;
1394  a->l2_table_index = last_table;
1395 
1396  /* Populate the classifier tables with rules from the MACIP ACL */
1397  for (i = 0; i < a->count; i++)
1398  {
1399  u32 action = 0;
1400  u32 metadata = 0;
1401  int is6 = a->rules[i].is_ipv6;
1402  int l3_src_offs = get_l3_src_offset (is6);
1403  u32 tag_table;
1404  int tags, eth;
1405 
1406  match_type_index =
1408  a->rules[i].src_prefixlen,
1409  a->rules[i].is_ipv6);
1410  ASSERT (match_type_index != ~0);
1411 
1412  l3_src_offs += 8;
1413  for (tags = 2; tags >= 0; tags--)
1414  {
1415  memset (mask, 0, sizeof (mask));
1416  memcpy (&mask[6], a->rules[i].src_mac, 6);
1417  switch (tags)
1418  {
1419  case 0:
1420  default:
1421  tag_table = mvec[match_type_index].table_index;
1422  eth = 12;
1423  break;
1424  case 1:
1425  tag_table = mvec[match_type_index].dot1q_table_index;
1426  mask[12] = 0x81;
1427  mask[13] = 0x00;
1428  eth = 16;
1429  break;
1430  case 2:
1431  tag_table = mvec[match_type_index].dot1ad_table_index;
1432  mask[12] = 0x88;
1433  mask[13] = 0xa8;
1434  mask[16] = 0x81;
1435  mask[17] = 0x00;
1436  eth = 20;
1437  break;
1438  }
1439  if (is6)
1440  {
1441  memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip6, 16);
1442  mask[eth] = 0x86;
1443  mask[eth + 1] = 0xdd;
1444  }
1445  else
1446  {
1447  memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip4, 4);
1448  mask[eth] = 0x08;
1449  mask[eth + 1] = 0x00;
1450  }
1451 
1452  /* add session to table mvec[match_type_index].table_index; */
1453  vnet_classify_add_del_session (cm, tag_table,
1454  mask, a->rules[i].is_permit ? ~0 : 0,
1455  i, 0, action, metadata, 1);
1456  memset (&mask[12], 0, sizeof (mask) - 12);
1457  l3_src_offs -= 4;
1458  }
1459 
1460  /* add ARP table entry too */
1461  if (!is6 && (mvec[match_type_index].arp_table_index != ~0))
1462  {
1463  memset (mask, 0, sizeof (mask));
1464  memcpy (&mask[6], a->rules[i].src_mac, 6);
1465  mask[12] = 0x08;
1466  mask[13] = 0x06;
1467  memcpy (&mask[14 + 8], a->rules[i].src_mac, 6);
1468  memcpy (&mask[14 + 14], &a->rules[i].src_ip_addr.ip4, 4);
1470  mvec
1471  [match_type_index].arp_table_index,
1472  mask, a->rules[i].is_permit ? ~0 : 0,
1473  i, 0, action, metadata, 1);
1474  }
1475  }
1476  return 0;
1477 }
1478 
1479 static void
1481 {
1483  macip_acl_list_t *a = pool_elt_at_index (am->macip_acls, macip_acl_index);
1484 
1485  if (a->ip4_table_index != ~0)
1486  {
1487  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0,
1488  &a->ip4_table_index, 0);
1489  a->ip4_table_index = ~0;
1490  }
1491  if (a->ip6_table_index != ~0)
1492  {
1493  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0,
1494  &a->ip6_table_index, 0);
1495  a->ip6_table_index = ~0;
1496  }
1497  if (a->l2_table_index != ~0)
1498  {
1499  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0, &a->l2_table_index,
1500  0);
1501  a->l2_table_index = ~0;
1502  }
1503 }
1504 
1505 static int
1507  int is_apply)
1508 {
1509  int rv = 0;
1510  int rv0 = 0;
1511  int i;
1512  macip_acl_list_t *a = pool_elt_at_index (am->macip_acls, acl_index);
1513 
1514  for (i = 0; i < vec_len (am->macip_acl_by_sw_if_index); i++)
1515  if (vec_elt (am->macip_acl_by_sw_if_index, i) == acl_index)
1516  {
1519  is_apply);
1520  /* return the first unhappy outcome but make try to plough through. */
1521  rv = rv || rv0;
1522  }
1523  return rv;
1524 }
1525 
1526 static int
1528  u32 * acl_list_index, u8 * tag)
1529 {
1530  acl_main_t *am = &acl_main;
1532  macip_acl_rule_t *r;
1533  macip_acl_rule_t *acl_new_rules = 0;
1534  int i;
1535  int rv = 0;
1536 
1537  if (*acl_list_index != ~0)
1538  {
1539  /* They supplied some number, let's see if this MACIP ACL exists */
1540  if (pool_is_free_index (am->macip_acls, *acl_list_index))
1541  {
1542  /* tried to replace a non-existent ACL, no point doing anything */
1543  clib_warning
1544  ("acl-plugin-error: Trying to replace nonexistent MACIP ACL %d (tag %s)",
1545  *acl_list_index, tag);
1546  return VNET_API_ERROR_NO_SUCH_ENTRY;
1547  }
1548  }
1549 
1550  if (0 == count)
1551  {
1552  clib_warning
1553  ("acl-plugin-warning: Trying to create empty MACIP ACL (tag %s)",
1554  tag);
1555  }
1556  /* if replacing the ACL, unapply the classifier tables first - they will be gone.. */
1557  if (~0 != *acl_list_index)
1558  rv = macip_maybe_apply_unapply_classifier_tables (am, *acl_list_index, 0);
1559  void *oldheap = acl_set_heap (am);
1560  /* Create and populate the rules */
1561  if (count > 0)
1562  vec_validate (acl_new_rules, count - 1);
1563 
1564  for (i = 0; i < count; i++)
1565  {
1566  r = &acl_new_rules[i];
1567  r->is_permit = rules[i].is_permit;
1568  r->is_ipv6 = rules[i].is_ipv6;
1569  memcpy (&r->src_mac, rules[i].src_mac, 6);
1570  memcpy (&r->src_mac_mask, rules[i].src_mac_mask, 6);
1571  if (rules[i].is_ipv6)
1572  memcpy (&r->src_ip_addr.ip6, rules[i].src_ip_addr, 16);
1573  else
1574  memcpy (&r->src_ip_addr.ip4, rules[i].src_ip_addr, 4);
1575  r->src_prefixlen = rules[i].src_ip_prefix_len;
1576  }
1577 
1578  if (~0 == *acl_list_index)
1579  {
1580  /* Get ACL index */
1582  memset (a, 0, sizeof (*a));
1583  /* Will return the newly allocated ACL index */
1584  *acl_list_index = a - am->macip_acls;
1585  }
1586  else
1587  {
1588  a = pool_elt_at_index (am->macip_acls, *acl_list_index);
1589  if (a->rules)
1590  {
1591  vec_free (a->rules);
1592  }
1593  macip_destroy_classify_tables (am, *acl_list_index);
1594  }
1595 
1596  a->rules = acl_new_rules;
1597  a->count = count;
1598  memcpy (a->tag, tag, sizeof (a->tag));
1599 
1600  /* Create and populate the classifer tables */
1601  macip_create_classify_tables (am, *acl_list_index);
1602  clib_mem_set_heap (oldheap);
1603  /* If the ACL was already applied somewhere, reapply the newly created tables */
1604  rv = rv
1605  || macip_maybe_apply_unapply_classifier_tables (am, *acl_list_index, 1);
1606  return rv;
1607 }
1608 
1609 
1610 /* No check for validity of sw_if_index - the callers were supposed to validate */
1611 
1612 static int
1614 {
1615  int rv;
1616  u32 macip_acl_index;
1618  void *oldheap = acl_set_heap (am);
1619  vec_validate_init_empty (am->macip_acl_by_sw_if_index, sw_if_index, ~0);
1620  clib_mem_set_heap (oldheap);
1621  macip_acl_index = am->macip_acl_by_sw_if_index[sw_if_index];
1622  /* No point in deleting MACIP ACL which is not applied */
1623  if (~0 == macip_acl_index)
1624  return VNET_API_ERROR_NO_SUCH_ENTRY;
1625  a = pool_elt_at_index (am->macip_acls, macip_acl_index);
1626  /* remove the classifier tables off the interface L2 ACL */
1627  rv =
1628  vnet_set_input_acl_intfc (am->vlib_main, sw_if_index, a->ip4_table_index,
1629  a->ip6_table_index, a->l2_table_index, 0);
1630  /* Unset the MACIP ACL index */
1631  am->macip_acl_by_sw_if_index[sw_if_index] = ~0;
1632  return rv;
1633 }
1634 
1635 /* No check for validity of sw_if_index - the callers were supposed to validate */
1636 
1637 static int
1639  u32 macip_acl_index)
1640 {
1642  int rv;
1643  if (pool_is_free_index (am->macip_acls, macip_acl_index))
1644  {
1645  return VNET_API_ERROR_NO_SUCH_ENTRY;
1646  }
1647  void *oldheap = acl_set_heap (am);
1648  a = pool_elt_at_index (am->macip_acls, macip_acl_index);
1649  vec_validate_init_empty (am->macip_acl_by_sw_if_index, sw_if_index, ~0);
1650  clib_mem_set_heap (oldheap);
1651  /* If there already a MACIP ACL applied, unapply it */
1652  if (~0 != am->macip_acl_by_sw_if_index[sw_if_index])
1653  macip_acl_interface_del_acl (am, sw_if_index);
1654  am->macip_acl_by_sw_if_index[sw_if_index] = macip_acl_index;
1655 
1656  /* Apply the classifier tables for L2 ACLs */
1657  rv =
1658  vnet_set_input_acl_intfc (am->vlib_main, sw_if_index, a->ip4_table_index,
1659  a->ip6_table_index, a->l2_table_index, 1);
1660  return rv;
1661 }
1662 
1663 static int
1664 macip_acl_del_list (u32 acl_list_index)
1665 {
1666  acl_main_t *am = &acl_main;
1668  int i;
1669  if (pool_is_free_index (am->macip_acls, acl_list_index))
1670  {
1671  return VNET_API_ERROR_NO_SUCH_ENTRY;
1672  }
1673 
1674  /* delete any references to the ACL */
1675  for (i = 0; i < vec_len (am->macip_acl_by_sw_if_index); i++)
1676  {
1677  if (am->macip_acl_by_sw_if_index[i] == acl_list_index)
1678  {
1680  }
1681  }
1682 
1683  void *oldheap = acl_set_heap (am);
1684  /* Now that classifier tables are detached, clean them up */
1685  macip_destroy_classify_tables (am, acl_list_index);
1686 
1687  /* now we can delete the ACL itself */
1688  a = pool_elt_at_index (am->macip_acls, acl_list_index);
1689  if (a->rules)
1690  {
1691  vec_free (a->rules);
1692  }
1693  pool_put (am->macip_acls, a);
1694  clib_mem_set_heap (oldheap);
1695  return 0;
1696 }
1697 
1698 
1699 static int
1701  u32 acl_list_index)
1702 {
1703  acl_main_t *am = &acl_main;
1704  int rv = -1;
1705  if (is_add)
1706  {
1707  rv = macip_acl_interface_add_acl (am, sw_if_index, acl_list_index);
1708  }
1709  else
1710  {
1711  rv = macip_acl_interface_del_acl (am, sw_if_index);
1712  }
1713  return rv;
1714 }
1715 
1716 /*
1717  * If the client does not allocate enough memory for a variable-length
1718  * message, and then proceed to use it as if the full memory allocated,
1719  * absent the check we happily consume that on the VPP side, and go
1720  * along as if nothing happened. However, the resulting
1721  * effects range from just garbage in the API decode
1722  * (because the decoder snoops too far), to potential memory
1723  * corruptions.
1724  *
1725  * This verifies that the actual length of the message is
1726  * at least expected_len, and complains loudly if it is not.
1727  *
1728  * A failing check here is 100% a software bug on the API user side,
1729  * so we might as well yell.
1730  *
1731  */
1732 static int
1733 verify_message_len (void *mp, u32 expected_len, char *where)
1734 {
1735  u32 supplied_len = vl_msg_api_get_msg_length (mp);
1736  if (supplied_len < expected_len)
1737  {
1738  clib_warning ("%s: Supplied message length %d is less than expected %d",
1739  where, supplied_len, expected_len);
1740  return 0;
1741  }
1742  else
1743  {
1744  return 1;
1745  }
1746 }
1747 
1748 /* API message handler */
1749 static void
1751 {
1753  acl_main_t *am = &acl_main;
1754  int rv;
1755  u32 acl_list_index = ntohl (mp->acl_index);
1756  u32 acl_count = ntohl (mp->count);
1757  u32 expected_len = sizeof (*mp) + acl_count * sizeof (mp->r[0]);
1758 
1759  if (verify_message_len (mp, expected_len, "acl_add_replace"))
1760  {
1761  rv = acl_add_list (acl_count, mp->r, &acl_list_index, mp->tag);
1762  }
1763  else
1764  {
1765  rv = VNET_API_ERROR_INVALID_VALUE;
1766  }
1767 
1768  /* *INDENT-OFF* */
1769  REPLY_MACRO2(VL_API_ACL_ADD_REPLACE_REPLY,
1770  ({
1771  rmp->acl_index = htonl(acl_list_index);
1772  }));
1773  /* *INDENT-ON* */
1774 }
1775 
1776 static void
1778 {
1779  acl_main_t *am = &acl_main;
1780  vl_api_acl_del_reply_t *rmp;
1781  int rv;
1782 
1783  rv = acl_del_list (ntohl (mp->acl_index));
1784 
1785  REPLY_MACRO (VL_API_ACL_DEL_REPLY);
1786 }
1787 
1788 static void
1790 {
1791  acl_main_t *am = &acl_main;
1793  u32 sw_if_index = ntohl (mp->sw_if_index);
1794  vl_api_acl_interface_add_del_reply_t *rmp;
1795  int rv = -1;
1796 
1797  if (pool_is_free_index (im->sw_interfaces, sw_if_index))
1798  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1799  else
1800  rv =
1801  acl_interface_add_del_inout_acl (sw_if_index, mp->is_add,
1802  mp->is_input, ntohl (mp->acl_index));
1803 
1804  REPLY_MACRO (VL_API_ACL_INTERFACE_ADD_DEL_REPLY);
1805 }
1806 
1807 static void
1810 {
1811  acl_main_t *am = &acl_main;
1812  vl_api_acl_interface_set_acl_list_reply_t *rmp;
1813  int rv = 0;
1814  int i;
1816  u32 sw_if_index = ntohl (mp->sw_if_index);
1817 
1818  if (pool_is_free_index (im->sw_interfaces, sw_if_index))
1819  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1820  else
1821  {
1822  acl_interface_reset_inout_acls (sw_if_index, 0);
1823  acl_interface_reset_inout_acls (sw_if_index, 1);
1824 
1825  for (i = 0; i < mp->count; i++)
1826  {
1827  if (acl_is_not_defined (am, ntohl (mp->acls[i])))
1828  {
1829  /* ACL does not exist, so we can not apply it */
1830  rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1831  }
1832  }
1833  if (0 == rv)
1834  {
1835  for (i = 0; i < mp->count; i++)
1836  {
1837  acl_interface_add_del_inout_acl (sw_if_index, 1,
1838  (i < mp->n_input),
1839  ntohl (mp->acls[i]));
1840  }
1841  }
1842  }
1843 
1844  REPLY_MACRO (VL_API_ACL_INTERFACE_SET_ACL_LIST_REPLY);
1845 }
1846 
1847 static void
1849 {
1850  api_rule->is_permit = r->is_permit;
1851  api_rule->is_ipv6 = r->is_ipv6;
1852  if (r->is_ipv6)
1853  {
1854  memcpy (api_rule->src_ip_addr, &r->src, sizeof (r->src));
1855  memcpy (api_rule->dst_ip_addr, &r->dst, sizeof (r->dst));
1856  }
1857  else
1858  {
1859  memcpy (api_rule->src_ip_addr, &r->src.ip4, sizeof (r->src.ip4));
1860  memcpy (api_rule->dst_ip_addr, &r->dst.ip4, sizeof (r->dst.ip4));
1861  }
1862  api_rule->src_ip_prefix_len = r->src_prefixlen;
1863  api_rule->dst_ip_prefix_len = r->dst_prefixlen;
1864  api_rule->proto = r->proto;
1865  api_rule->srcport_or_icmptype_first = htons (r->src_port_or_type_first);
1866  api_rule->srcport_or_icmptype_last = htons (r->src_port_or_type_last);
1867  api_rule->dstport_or_icmpcode_first = htons (r->dst_port_or_code_first);
1868  api_rule->dstport_or_icmpcode_last = htons (r->dst_port_or_code_last);
1869  api_rule->tcp_flags_mask = r->tcp_flags_mask;
1870  api_rule->tcp_flags_value = r->tcp_flags_value;
1871 }
1872 
1873 static void
1875  acl_list_t * acl, u32 context)
1876 {
1878  vl_api_acl_rule_t *rules;
1879  int i;
1880  int msg_size = sizeof (*mp) + sizeof (mp->r[0]) * acl->count;
1881  void *oldheap = acl_set_heap (am);
1882 
1883  mp = vl_msg_api_alloc (msg_size);
1884  memset (mp, 0, msg_size);
1885  mp->_vl_msg_id = ntohs (VL_API_ACL_DETAILS + am->msg_id_base);
1886 
1887  /* fill in the message */
1888  mp->context = context;
1889  mp->count = htonl (acl->count);
1890  mp->acl_index = htonl (acl - am->acls);
1891  memcpy (mp->tag, acl->tag, sizeof (mp->tag));
1892  // clib_memcpy (mp->r, acl->rules, acl->count * sizeof(acl->rules[0]));
1893  rules = mp->r;
1894  for (i = 0; i < acl->count; i++)
1895  {
1896  copy_acl_rule_to_api_rule (&rules[i], &acl->rules[i]);
1897  }
1898 
1899  clib_mem_set_heap (oldheap);
1900  vl_msg_api_send_shmem (q, (u8 *) & mp);
1901 }
1902 
1903 
1904 static void
1906 {
1907  acl_main_t *am = &acl_main;
1908  u32 acl_index;
1909  acl_list_t *acl;
1910 
1911  int rv = -1;
1913 
1915  if (q == 0)
1916  {
1917  return;
1918  }
1919 
1920  if (mp->acl_index == ~0)
1921  {
1922  /* *INDENT-OFF* */
1923  /* Just dump all ACLs */
1924  pool_foreach (acl, am->acls,
1925  ({
1926  send_acl_details(am, q, acl, mp->context);
1927  }));
1928  /* *INDENT-ON* */
1929  }
1930  else
1931  {
1932  acl_index = ntohl (mp->acl_index);
1933  if (!pool_is_free_index (am->acls, acl_index))
1934  {
1935  acl = pool_elt_at_index (am->acls, acl_index);
1936  send_acl_details (am, q, acl, mp->context);
1937  }
1938  }
1939 
1940  if (rv == -1)
1941  {
1942  /* FIXME API: should we signal an error here at all ? */
1943  return;
1944  }
1945 }
1946 
1947 static void
1950  u32 sw_if_index, u32 context)
1951 {
1953  int msg_size;
1954  int n_input;
1955  int n_output;
1956  int count;
1957  int i = 0;
1958  void *oldheap = acl_set_heap (am);
1959 
1960  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
1961  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
1962 
1963  n_input = vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]);
1964  n_output = vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]);
1965  count = n_input + n_output;
1966 
1967  msg_size = sizeof (*mp);
1968  msg_size += sizeof (mp->acls[0]) * count;
1969 
1970  mp = vl_msg_api_alloc (msg_size);
1971  memset (mp, 0, msg_size);
1972  mp->_vl_msg_id =
1973  ntohs (VL_API_ACL_INTERFACE_LIST_DETAILS + am->msg_id_base);
1974 
1975  /* fill in the message */
1976  mp->context = context;
1977  mp->sw_if_index = htonl (sw_if_index);
1978  mp->count = count;
1979  mp->n_input = n_input;
1980  for (i = 0; i < n_input; i++)
1981  {
1982  mp->acls[i] = htonl (am->input_acl_vec_by_sw_if_index[sw_if_index][i]);
1983  }
1984  for (i = 0; i < n_output; i++)
1985  {
1986  mp->acls[n_input + i] =
1987  htonl (am->output_acl_vec_by_sw_if_index[sw_if_index][i]);
1988  }
1989  clib_mem_set_heap (oldheap);
1990  vl_msg_api_send_shmem (q, (u8 *) & mp);
1991 }
1992 
1993 static void
1995  mp)
1996 {
1997  acl_main_t *am = &acl_main;
1998  vnet_sw_interface_t *swif;
2000 
2001  u32 sw_if_index;
2003 
2005  if (q == 0)
2006  {
2007  return;
2008  }
2009 
2010  if (mp->sw_if_index == ~0)
2011  {
2012  /* *INDENT-OFF* */
2013  pool_foreach (swif, im->sw_interfaces,
2014  ({
2015  send_acl_interface_list_details(am, q, swif->sw_if_index, mp->context);
2016  }));
2017  /* *INDENT-ON* */
2018  }
2019  else
2020  {
2021  sw_if_index = ntohl (mp->sw_if_index);
2022  if (!pool_is_free_index (im->sw_interfaces, sw_if_index))
2023  send_acl_interface_list_details (am, q, sw_if_index, mp->context);
2024  }
2025 }
2026 
2027 /* MACIP ACL API handlers */
2028 
2029 static void
2031 {
2033  acl_main_t *am = &acl_main;
2034  int rv;
2035  u32 acl_list_index = ~0;
2036  u32 acl_count = ntohl (mp->count);
2037  u32 expected_len = sizeof (*mp) + acl_count * sizeof (mp->r[0]);
2038 
2039  if (verify_message_len (mp, expected_len, "macip_acl_add"))
2040  {
2041  rv = macip_acl_add_list (acl_count, mp->r, &acl_list_index, mp->tag);
2042  }
2043  else
2044  {
2045  rv = VNET_API_ERROR_INVALID_VALUE;
2046  }
2047 
2048  /* *INDENT-OFF* */
2049  REPLY_MACRO2(VL_API_MACIP_ACL_ADD_REPLY,
2050  ({
2051  rmp->acl_index = htonl(acl_list_index);
2052  }));
2053  /* *INDENT-ON* */
2054 }
2055 
2056 static void
2058 {
2060  acl_main_t *am = &acl_main;
2061  int rv;
2062  u32 acl_list_index = ntohl (mp->acl_index);
2063  u32 acl_count = ntohl (mp->count);
2064  u32 expected_len = sizeof (*mp) + acl_count * sizeof (mp->r[0]);
2065 
2066  if (verify_message_len (mp, expected_len, "macip_acl_add_replace"))
2067  {
2068  rv = macip_acl_add_list (acl_count, mp->r, &acl_list_index, mp->tag);
2069  }
2070  else
2071  {
2072  rv = VNET_API_ERROR_INVALID_VALUE;
2073  }
2074 
2075  /* *INDENT-OFF* */
2076  REPLY_MACRO2(VL_API_MACIP_ACL_ADD_REPLACE_REPLY,
2077  ({
2078  rmp->acl_index = htonl(acl_list_index);
2079  }));
2080  /* *INDENT-ON* */
2081 }
2082 
2083 static void
2085 {
2086  acl_main_t *am = &acl_main;
2087  vl_api_macip_acl_del_reply_t *rmp;
2088  int rv;
2089 
2090  rv = macip_acl_del_list (ntohl (mp->acl_index));
2091 
2092  REPLY_MACRO (VL_API_MACIP_ACL_DEL_REPLY);
2093 }
2094 
2095 static void
2098 {
2099  acl_main_t *am = &acl_main;
2100  vl_api_macip_acl_interface_add_del_reply_t *rmp;
2101  int rv = -1;
2103  u32 sw_if_index = ntohl (mp->sw_if_index);
2104 
2105  if (pool_is_free_index (im->sw_interfaces, sw_if_index))
2106  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
2107  else
2108  rv =
2110  ntohl (mp->acl_index));
2111 
2112  REPLY_MACRO (VL_API_MACIP_ACL_INTERFACE_ADD_DEL_REPLY);
2113 }
2114 
2115 static void
2117  macip_acl_list_t * acl, u32 context)
2118 {
2120  vl_api_macip_acl_rule_t *rules;
2121  macip_acl_rule_t *r;
2122  int i;
2123  int msg_size = sizeof (*mp) + (acl ? sizeof (mp->r[0]) * acl->count : 0);
2124 
2125  mp = vl_msg_api_alloc (msg_size);
2126  memset (mp, 0, msg_size);
2127  mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_DETAILS + am->msg_id_base);
2128 
2129  /* fill in the message */
2130  mp->context = context;
2131  if (acl)
2132  {
2133  memcpy (mp->tag, acl->tag, sizeof (mp->tag));
2134  mp->count = htonl (acl->count);
2135  mp->acl_index = htonl (acl - am->macip_acls);
2136  rules = mp->r;
2137  for (i = 0; i < acl->count; i++)
2138  {
2139  r = &acl->rules[i];
2140  rules[i].is_permit = r->is_permit;
2141  rules[i].is_ipv6 = r->is_ipv6;
2142  memcpy (rules[i].src_mac, &r->src_mac, sizeof (r->src_mac));
2143  memcpy (rules[i].src_mac_mask, &r->src_mac_mask,
2144  sizeof (r->src_mac_mask));
2145  if (r->is_ipv6)
2146  memcpy (rules[i].src_ip_addr, &r->src_ip_addr.ip6,
2147  sizeof (r->src_ip_addr.ip6));
2148  else
2149  memcpy (rules[i].src_ip_addr, &r->src_ip_addr.ip4,
2150  sizeof (r->src_ip_addr.ip4));
2151  rules[i].src_ip_prefix_len = r->src_prefixlen;
2152  }
2153  }
2154  else
2155  {
2156  /* No martini, no party - no ACL applied to this interface. */
2157  mp->acl_index = ~0;
2158  mp->count = 0;
2159  }
2160 
2161  vl_msg_api_send_shmem (q, (u8 *) & mp);
2162 }
2163 
2164 
2165 static void
2167 {
2168  acl_main_t *am = &acl_main;
2169  macip_acl_list_t *acl;
2170 
2172 
2174  if (q == 0)
2175  {
2176  return;
2177  }
2178 
2179  if (mp->acl_index == ~0)
2180  {
2181  /* Just dump all ACLs for now, with sw_if_index = ~0 */
2182  pool_foreach (acl, am->macip_acls, (
2183  {
2184  send_macip_acl_details (am, q, acl,
2185  mp->
2186  context);}
2187  ));
2188  /* *INDENT-ON* */
2189  }
2190  else
2191  {
2192  u32 acl_index = ntohl (mp->acl_index);
2193  if (!pool_is_free_index (am->macip_acls, acl_index))
2194  {
2195  acl = pool_elt_at_index (am->macip_acls, acl_index);
2196  send_macip_acl_details (am, q, acl, mp->context);
2197  }
2198  }
2199 }
2200 
2201 static void
2203  mp)
2204 {
2205  acl_main_t *am = &acl_main;
2208  int msg_size = sizeof (*rmp) + sizeof (rmp->acls[0]) * count;
2210  int i;
2211 
2213  if (q == 0)
2214  {
2215  return;
2216  }
2217 
2218  rmp = vl_msg_api_alloc (msg_size);
2219  memset (rmp, 0, msg_size);
2220  rmp->_vl_msg_id =
2221  ntohs (VL_API_MACIP_ACL_INTERFACE_GET_REPLY + am->msg_id_base);
2222  rmp->context = mp->context;
2223  rmp->count = htonl (count);
2224  for (i = 0; i < count; i++)
2225  {
2226  rmp->acls[i] = htonl (am->macip_acl_by_sw_if_index[i]);
2227  }
2228 
2229  vl_msg_api_send_shmem (q, (u8 *) & rmp);
2230 }
2231 
2232 static void
2235  u32 sw_if_index,
2236  u32 acl_index, u32 context)
2237 {
2239  /* at this time there is only ever 1 mac ip acl per interface */
2240  int msg_size = sizeof (*rmp) + sizeof (rmp->acls[0]);
2241 
2242  rmp = vl_msg_api_alloc (msg_size);
2243  memset (rmp, 0, msg_size);
2244  rmp->_vl_msg_id =
2245  ntohs (VL_API_MACIP_ACL_INTERFACE_LIST_DETAILS + am->msg_id_base);
2246 
2247  /* fill in the message */
2248  rmp->context = context;
2249  rmp->count = 1;
2250  rmp->sw_if_index = htonl (sw_if_index);
2251  rmp->acls[0] = htonl (acl_index);
2252 
2253  vl_msg_api_send_shmem (q, (u8 *) & rmp);
2254 }
2255 
2256 static void
2259 {
2261  acl_main_t *am = &acl_main;
2262  u32 sw_if_index = ntohl (mp->sw_if_index);
2263 
2265  if (q == 0)
2266  {
2267  return;
2268  }
2269 
2270  if (sw_if_index == ~0)
2271  {
2272  vec_foreach_index (sw_if_index, am->macip_acl_by_sw_if_index)
2273  {
2274  if (~0 != am->macip_acl_by_sw_if_index[sw_if_index])
2275  {
2276  send_macip_acl_interface_list_details (am, q, sw_if_index,
2278  [sw_if_index],
2279  mp->context);
2280  }
2281  }
2282  }
2283  else
2284  {
2285  if (vec_len (am->macip_acl_by_sw_if_index) > sw_if_index)
2286  {
2287  send_macip_acl_interface_list_details (am, q, sw_if_index,
2289  [sw_if_index], mp->context);
2290  }
2291  }
2292 }
2293 
2294 /* Set up the API message handling tables */
2295 static clib_error_t *
2297 {
2298  acl_main_t *am = &acl_main;
2299 #define _(N,n) \
2300  vl_msg_api_set_handlers((VL_API_##N + am->msg_id_base), \
2301  #n, \
2302  vl_api_##n##_t_handler, \
2303  vl_noop_handler, \
2304  vl_api_##n##_t_endian, \
2305  vl_api_##n##_t_print, \
2306  sizeof(vl_api_##n##_t), 1);
2308 #undef _
2309 
2310  return 0;
2311 }
2312 
2313 #define vl_msg_name_crc_list
2314 #include <acl/acl_all_api_h.h>
2315 #undef vl_msg_name_crc_list
2316 
2317 static void
2319 {
2320 #define _(id,n,crc) \
2321  vl_msg_api_add_msg_name_crc (apim, #n "_" #crc, id + am->msg_id_base);
2322  foreach_vl_msg_name_crc_acl;
2323 #undef _
2324 }
2325 
2326 static void
2328 {
2330  acl_main_t *am = &acl_main;
2331  vlib_node_t *n, *n4, *n6;
2332 
2333  n = vlib_get_node_by_name (vm, (u8 *) "l2-input-classify");
2334  n4 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-in-ip4-l2");
2335  n6 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-in-ip6-l2");
2336 
2337 
2339  vlib_node_add_next_with_slot (vm, n->index, n4->index, ~0);
2341  vlib_node_add_next_with_slot (vm, n->index, n6->index, ~0);
2342 
2346 
2350 
2351 
2352  n = vlib_get_node_by_name (vm, (u8 *) "l2-output-classify");
2353  n4 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-out-ip4-l2");
2354  n6 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-out-ip6-l2");
2355 
2357  vlib_node_add_next_with_slot (vm, n->index, n4->index, ~0);
2359  vlib_node_add_next_with_slot (vm, n->index, n6->index, ~0);
2360 
2364 
2368 }
2369 
2370 static void
2371 acl_set_timeout_sec (int timeout_type, u32 value)
2372 {
2373  acl_main_t *am = &acl_main;
2374  clib_time_t *ct = &am->vlib_main->clib_time;
2375 
2376  if (timeout_type < ACL_N_TIMEOUTS)
2377  {
2378  am->session_timeout_sec[timeout_type] = value;
2379  }
2380  else
2381  {
2382  clib_warning ("Unknown timeout type %d", timeout_type);
2383  return;
2384  }
2385  am->session_timeout[timeout_type] =
2386  (u64) (((f64) value) / ct->seconds_per_clock);
2387 }
2388 
2389 static void
2391 {
2392  acl_main_t *am = &acl_main;
2393  am->fa_conn_table_max_entries = value;
2394 }
2395 
2396 static int
2398 {
2399  acl_main_t *am = &acl_main;
2400 
2401  if ((eh < 256) && (value < 2))
2402  {
2404  clib_bitmap_set (am->fa_ipv6_known_eh_bitmap, eh, value);
2405  return 1;
2406  }
2407  else
2408  return 0;
2409 }
2410 
2411 
2412 static clib_error_t *
2413 acl_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
2414 {
2415  acl_main_t *am = &acl_main;
2416  if (0 == am->acl_mheap)
2417  {
2418  /* ACL heap is not initialized, so definitely nothing to do. */
2419  return 0;
2420  }
2421  if (0 == is_add)
2422  {
2425  sw_if_index);
2426  /* also unapply any ACLs in case the users did not do so. */
2427  macip_acl_interface_del_acl (am, sw_if_index);
2428  acl_interface_reset_inout_acls (sw_if_index, 0);
2429  acl_interface_reset_inout_acls (sw_if_index, 1);
2430  }
2431  return 0;
2432 }
2433 
2435 
2436 
2437 
2438 static clib_error_t *
2440  unformat_input_t * input, vlib_cli_command_t * cmd)
2441 {
2442  clib_error_t *error = 0;
2443  u32 timeout = 0;
2444  u32 val = 0;
2445  u32 eh_val = 0;
2446  uword memory_size = 0;
2447  acl_main_t *am = &acl_main;
2448 
2449  if (unformat (input, "skip-ipv6-extension-header %u %u", &eh_val, &val))
2450  {
2451  if (!acl_set_skip_ipv6_eh (eh_val, val))
2452  {
2453  error = clib_error_return (0, "expecting eh=0..255, value=0..1");
2454  }
2455  goto done;
2456  }
2457  if (unformat (input, "use-hash-acl-matching %u", &val))
2458  {
2459  am->use_hash_acl_matching = (val != 0);
2460  goto done;
2461  }
2462  if (unformat (input, "l4-match-nonfirst-fragment %u", &val))
2463  {
2464  am->l4_match_nonfirst_fragment = (val != 0);
2465  goto done;
2466  }
2467  if (unformat (input, "heap"))
2468  {
2469  if (unformat (input, "main"))
2470  {
2471  if (unformat (input, "validate %u", &val))
2473  else if (unformat (input, "trace %u", &val))
2475  goto done;
2476  }
2477  else if (unformat (input, "hash"))
2478  {
2479  if (unformat (input, "validate %u", &val))
2481  else if (unformat (input, "trace %u", &val))
2483  goto done;
2484  }
2485  goto done;
2486  }
2487  if (unformat (input, "session"))
2488  {
2489  if (unformat (input, "table"))
2490  {
2491  /* The commands here are for tuning/testing. No user-serviceable parts inside */
2492  if (unformat (input, "max-entries"))
2493  {
2494  if (!unformat (input, "%u", &val))
2495  {
2496  error = clib_error_return (0,
2497  "expecting maximum number of entries, got `%U`",
2498  format_unformat_error, input);
2499  goto done;
2500  }
2501  else
2502  {
2504  goto done;
2505  }
2506  }
2507  if (unformat (input, "hash-table-buckets"))
2508  {
2509  if (!unformat (input, "%u", &val))
2510  {
2511  error = clib_error_return (0,
2512  "expecting maximum number of hash table buckets, got `%U`",
2513  format_unformat_error, input);
2514  goto done;
2515  }
2516  else
2517  {
2519  goto done;
2520  }
2521  }
2522  if (unformat (input, "hash-table-memory"))
2523  {
2524  if (!unformat (input, "%U", unformat_memory_size, &memory_size))
2525  {
2526  error = clib_error_return (0,
2527  "expecting maximum amount of hash table memory, got `%U`",
2528  format_unformat_error, input);
2529  goto done;
2530  }
2531  else
2532  {
2534  goto done;
2535  }
2536  }
2537  goto done;
2538  }
2539  if (unformat (input, "timeout"))
2540  {
2541  if (unformat (input, "udp"))
2542  {
2543  if (unformat (input, "idle"))
2544  {
2545  if (!unformat (input, "%u", &timeout))
2546  {
2547  error = clib_error_return (0,
2548  "expecting timeout value in seconds, got `%U`",
2550  input);
2551  goto done;
2552  }
2553  else
2554  {
2556  goto done;
2557  }
2558  }
2559  }
2560  if (unformat (input, "tcp"))
2561  {
2562  if (unformat (input, "idle"))
2563  {
2564  if (!unformat (input, "%u", &timeout))
2565  {
2566  error = clib_error_return (0,
2567  "expecting timeout value in seconds, got `%U`",
2569  input);
2570  goto done;
2571  }
2572  else
2573  {
2575  goto done;
2576  }
2577  }
2578  if (unformat (input, "transient"))
2579  {
2580  if (!unformat (input, "%u", &timeout))
2581  {
2582  error = clib_error_return (0,
2583  "expecting timeout value in seconds, got `%U`",
2585  input);
2586  goto done;
2587  }
2588  else
2589  {
2591  timeout);
2592  goto done;
2593  }
2594  }
2595  }
2596  goto done;
2597  }
2598  }
2599 done:
2600  return error;
2601 }
2602 
2603 static u8 *
2604 my_format_mac_address (u8 * s, va_list * args)
2605 {
2606  u8 *a = va_arg (*args, u8 *);
2607  return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
2608  a[0], a[1], a[2], a[3], a[4], a[5]);
2609 }
2610 
2611 static inline u8 *
2612 my_macip_acl_rule_t_pretty_format (u8 * out, va_list * args)
2613 {
2614  macip_acl_rule_t *a = va_arg (*args, macip_acl_rule_t *);
2615 
2616  out = format (out, "%s action %d ip %U/%d mac %U mask %U",
2617  a->is_ipv6 ? "ipv6" : "ipv4", a->is_permit,
2620  a->src_prefixlen,
2623  return (out);
2624 }
2625 
2626 static void
2627 macip_acl_print (acl_main_t * am, u32 macip_acl_index)
2628 {
2629  vlib_main_t *vm = am->vlib_main;
2630  int i;
2631 
2632  /* Don't try to print someone else's memory */
2633  if (macip_acl_index > vec_len (am->macip_acls))
2634  return;
2635 
2636  macip_acl_list_t *a = vec_elt_at_index (am->macip_acls, macip_acl_index);
2637  int free_pool_slot = pool_is_free_index (am->macip_acls, macip_acl_index);
2638 
2639  vlib_cli_output (vm,
2640  "MACIP acl_index: %d, count: %d (true len %d) tag {%s} is free pool slot: %d\n",
2641  macip_acl_index, a->count, vec_len (a->rules), a->tag,
2642  free_pool_slot);
2643  vlib_cli_output (vm,
2644  " ip4_table_index %d, ip6_table_index %d, l2_table_index %d\n",
2646  for (i = 0; i < vec_len (a->rules); i++)
2647  vlib_cli_output (vm, " rule %d: %U\n", i,
2649  vec_elt_at_index (a->rules, i));
2650 
2651 }
2652 
2653 static clib_error_t *
2655  unformat_input_t * input,
2656  vlib_cli_command_t * cmd)
2657 {
2658  clib_error_t *error = 0;
2659  acl_main_t *am = &acl_main;
2660  int i;
2661  for (i = 0; i < vec_len (am->macip_acls); i++)
2662  macip_acl_print (am, i);
2663  return error;
2664 }
2665 
2666 static clib_error_t *
2668  unformat_input_t * input,
2669  vlib_cli_command_t * cmd)
2670 {
2671  clib_error_t *error = 0;
2672  acl_main_t *am = &acl_main;
2673  int i;
2674  for (i = 0; i < vec_len (am->macip_acl_by_sw_if_index); i++)
2675  {
2676  vlib_cli_output (vm, " sw_if_index %d: %d\n", i,
2678  }
2679  return error;
2680 }
2681 
2682 #define PRINT_AND_RESET(vm, out0) do { vlib_cli_output(vm, "%v", out0); vec_reset_length(out0); } while(0)
2683 static void
2684 acl_print_acl (vlib_main_t * vm, acl_main_t * am, int acl_index)
2685 {
2686  acl_rule_t *r;
2687  u8 *out0 = format (0, "acl-index %u count %u tag {%s}\n", acl_index,
2688  am->acls[acl_index].count, am->acls[acl_index].tag);
2689  int j;
2690  PRINT_AND_RESET (vm, out0);
2691  for (j = 0; j < am->acls[acl_index].count; j++)
2692  {
2693  r = &am->acls[acl_index].rules[j];
2694  out0 = format (out0, " %4d: %s ", j, r->is_ipv6 ? "ipv6" : "ipv4");
2695  out0 = format_acl_action (out0, r->is_permit);
2696  out0 = format (out0, " src %U/%d", format_ip46_address, &r->src,
2698  r->src_prefixlen);
2699  out0 =
2700  format (out0, " dst %U/%d", format_ip46_address, &r->dst,
2701  r->is_ipv6 ? IP46_TYPE_IP6 : IP46_TYPE_IP4, r->dst_prefixlen);
2702  out0 = format (out0, " proto %d", r->proto);
2703  out0 = format (out0, " sport %d", r->src_port_or_type_first);
2705  {
2706  out0 = format (out0, "-%d", r->src_port_or_type_last);
2707  }
2708  out0 = format (out0, " dport %d", r->dst_port_or_code_first);
2710  {
2711  out0 = format (out0, "-%d", r->dst_port_or_code_last);
2712  }
2713  if (r->tcp_flags_mask || r->tcp_flags_value)
2714  {
2715  out0 =
2716  format (out0, " tcpflags %d mask %d", r->tcp_flags_value,
2717  r->tcp_flags_mask);
2718  }
2719  out0 = format (out0, "\n");
2720  PRINT_AND_RESET (vm, out0);
2721  }
2722 }
2723 
2724 #undef PRINT_AND_RESET
2725 
2726 static void
2728 {
2729  u32 i;
2730  vlib_main_t *vm = am->vlib_main;
2731 
2732  for (i = 0; i < vec_len (am->acls); i++)
2733  {
2734  if (acl_is_not_defined (am, i))
2735  {
2736  /* don't attempt to show the ACLs that do not exist */
2737  continue;
2738  }
2739  if ((acl_index != ~0) && (acl_index != i))
2740  {
2741  continue;
2742  }
2743  acl_print_acl (vm, am, i);
2744 
2745  if (i < vec_len (am->input_sw_if_index_vec_by_acl))
2746  {
2747  vlib_cli_output (vm, " applied inbound on sw_if_index: %U\n",
2749  "%d");
2750  }
2751  if (i < vec_len (am->output_sw_if_index_vec_by_acl))
2752  {
2753  vlib_cli_output (vm, " applied outbound on sw_if_index: %U\n",
2755  "%d");
2756  }
2757  }
2758 }
2759 
2760 static clib_error_t *
2762  unformat_input_t * input, vlib_cli_command_t * cmd)
2763 {
2764  clib_error_t *error = 0;
2765  acl_main_t *am = &acl_main;
2766 
2767  u32 acl_index = ~0;
2768  (void) unformat (input, "index %u", &acl_index);
2769 
2770  acl_plugin_show_acl (am, acl_index);
2771  return error;
2772 }
2773 
2774 static void
2775 acl_plugin_show_interface (acl_main_t * am, u32 sw_if_index, int show_acl)
2776 {
2777  vlib_main_t *vm = am->vlib_main;
2778  u32 swi;
2779  u32 *pj;
2780  for (swi = 0; (swi < vec_len (am->input_acl_vec_by_sw_if_index)) ||
2781  (swi < vec_len (am->output_acl_vec_by_sw_if_index)); swi++)
2782  {
2783  /* if we need a particular interface, skip all the others */
2784  if ((sw_if_index != ~0) && (sw_if_index != swi))
2785  continue;
2786 
2787  vlib_cli_output (vm, "sw_if_index %d:\n", swi);
2788 
2789  if ((swi < vec_len (am->input_acl_vec_by_sw_if_index)) &&
2790  (vec_len (am->input_acl_vec_by_sw_if_index[swi]) > 0))
2791  {
2792  vlib_cli_output (vm, " input acl(s): %U", format_vec32,
2793  am->input_acl_vec_by_sw_if_index[swi], "%d");
2794  if (show_acl)
2795  {
2796  vlib_cli_output (vm, "\n");
2798  {
2799  acl_print_acl (vm, am, *pj);
2800  }
2801  vlib_cli_output (vm, "\n");
2802  }
2803  }
2804 
2805  if ((swi < vec_len (am->output_acl_vec_by_sw_if_index)) &&
2806  (vec_len (am->output_acl_vec_by_sw_if_index[swi]) > 0))
2807  {
2808  vlib_cli_output (vm, " output acl(s): %U", format_vec32,
2809  am->output_acl_vec_by_sw_if_index[swi], "%d");
2810  if (show_acl)
2811  {
2812  vlib_cli_output (vm, "\n");
2814  {
2815  acl_print_acl (vm, am, *pj);
2816  }
2817  vlib_cli_output (vm, "\n");
2818  }
2819  }
2820  }
2821 
2822 }
2823 
2824 
2825 static clib_error_t *
2827  unformat_input_t * input,
2828  vlib_cli_command_t * cmd)
2829 {
2830  clib_error_t *error = 0;
2831  u64 five_tuple[6] = { 0, 0, 0, 0, 0, 0 };
2832 
2833  if (unformat
2834  (input, "%llx %llx %llx %llx %llx %llx", &five_tuple[0], &five_tuple[1],
2835  &five_tuple[2], &five_tuple[3], &five_tuple[4], &five_tuple[5]))
2836  vlib_cli_output (vm, "5-tuple structure decode: %U\n\n",
2837  format_acl_plugin_5tuple, five_tuple);
2838  else
2839  error = clib_error_return (0, "expecting 6 hex integers");
2840  return error;
2841 }
2842 
2843 
2844 static clib_error_t *
2846  unformat_input_t * input,
2847  vlib_cli_command_t * cmd)
2848 {
2849  clib_error_t *error = 0;
2850  acl_main_t *am = &acl_main;
2851 
2852  u32 sw_if_index = ~0;
2853  (void) unformat (input, "sw_if_index %u", &sw_if_index);
2854  int show_acl = unformat (input, "acl");
2855 
2856  acl_plugin_show_interface (am, sw_if_index, show_acl);
2857  return error;
2858 }
2859 
2860 static clib_error_t *
2862  unformat_input_t * input,
2863  vlib_cli_command_t * cmd)
2864 {
2865  clib_error_t *error = 0;
2866  acl_main_t *am = &acl_main;
2867 
2868  vlib_cli_output (vm, "ACL plugin main heap statistics:\n");
2869  if (am->acl_mheap)
2870  {
2871  vlib_cli_output (vm, " %U\n", format_mheap, am->acl_mheap, 1);
2872  }
2873  else
2874  {
2875  vlib_cli_output (vm, " Not initialized\n");
2876  }
2877  vlib_cli_output (vm, "ACL hash lookup support heap statistics:\n");
2878  if (am->hash_lookup_mheap)
2879  {
2880  vlib_cli_output (vm, " %U\n", format_mheap, am->hash_lookup_mheap, 1);
2881  }
2882  else
2883  {
2884  vlib_cli_output (vm, " Not initialized\n");
2885  }
2886  return error;
2887 }
2888 
2889 static void
2891  u32 show_session_thread_id,
2892  u32 show_session_session_index)
2893 {
2894  vlib_main_t *vm = am->vlib_main;
2895  u16 wk;
2897  vnet_sw_interface_t *swif;
2898 
2899  {
2900  u64 n_adds = am->fa_session_total_adds;
2901  u64 n_dels = am->fa_session_total_dels;
2902  vlib_cli_output (vm, "Sessions total: add %lu - del %lu = %lu", n_adds,
2903  n_dels, n_adds - n_dels);
2904  }
2905  vlib_cli_output (vm, "\n\nPer-thread data:");
2906  for (wk = 0; wk < vec_len (am->per_worker_data); wk++)
2907  {
2909  vlib_cli_output (vm, "Thread #%d:", wk);
2910  if (show_session_thread_id == wk
2911  && show_session_session_index < pool_len (pw->fa_sessions_pool))
2912  {
2913  vlib_cli_output (vm, " session index %u:",
2914  show_session_session_index);
2915  fa_session_t *sess =
2916  pw->fa_sessions_pool + show_session_session_index;
2917  u64 *m = (u64 *) & sess->info;
2918  vlib_cli_output (vm,
2919  " info: %016llx %016llx %016llx %016llx %016llx %016llx",
2920  m[0], m[1], m[2], m[3], m[4], m[5]);
2921  vlib_cli_output (vm, " sw_if_index: %u", sess->sw_if_index);
2922  vlib_cli_output (vm, " tcp_flags_seen: %x",
2923  sess->tcp_flags_seen.as_u16);
2924  vlib_cli_output (vm, " last active time: %lu",
2925  sess->last_active_time);
2926  vlib_cli_output (vm, " thread index: %u", sess->thread_index);
2927  vlib_cli_output (vm, " link enqueue time: %lu",
2928  sess->link_enqueue_time);
2929  vlib_cli_output (vm, " link next index: %u",
2930  sess->link_next_idx);
2931  vlib_cli_output (vm, " link prev index: %u",
2932  sess->link_prev_idx);
2933  vlib_cli_output (vm, " link list id: %u", sess->link_list_id);
2934  }
2935  vlib_cli_output (vm, " connection add/del stats:", wk);
2936  pool_foreach (swif, im->sw_interfaces, (
2937  {
2938  u32 sw_if_index =
2939  swif->sw_if_index;
2940  u64 n_adds =
2941  sw_if_index <
2942  vec_len
2943  (pw->fa_session_adds_by_sw_if_index)
2944  ?
2945  pw->fa_session_adds_by_sw_if_index
2946  [sw_if_index] : 0;
2947  u64 n_dels =
2948  sw_if_index <
2949  vec_len
2950  (pw->fa_session_dels_by_sw_if_index)
2951  ?
2952  pw->fa_session_dels_by_sw_if_index
2953  [sw_if_index] : 0;
2954  vlib_cli_output (vm,
2955  " sw_if_index %d: add %lu - del %lu = %lu",
2956  sw_if_index,
2957  n_adds,
2958  n_dels,
2959  n_adds -
2960  n_dels);
2961  }
2962  ));
2963 
2964  vlib_cli_output (vm, " connection timeout type lists:", wk);
2965  u8 tt = 0;
2966  for (tt = 0; tt < ACL_N_TIMEOUTS; tt++)
2967  {
2968  u32 head_session_index = pw->fa_conn_list_head[tt];
2969  vlib_cli_output (vm, " fa_conn_list_head[%d]: %d", tt,
2970  head_session_index);
2971  if (~0 != head_session_index)
2972  {
2973  fa_session_t *sess = pw->fa_sessions_pool + head_session_index;
2974  vlib_cli_output (vm, " last active time: %lu",
2975  sess->last_active_time);
2976  vlib_cli_output (vm, " link enqueue time: %lu",
2977  sess->link_enqueue_time);
2978  }
2979  }
2980 
2981  vlib_cli_output (vm, " Next expiry time: %lu", pw->next_expiry_time);
2982  vlib_cli_output (vm, " Requeue until time: %lu",
2983  pw->requeue_until_time);
2984  vlib_cli_output (vm, " Current time wait interval: %lu",
2986  vlib_cli_output (vm, " Count of deleted sessions: %lu",
2987  pw->cnt_deleted_sessions);
2988  vlib_cli_output (vm, " Delete already deleted: %lu",
2990  vlib_cli_output (vm, " Session timers restarted: %lu",
2992  vlib_cli_output (vm, " Swipe until this time: %lu",
2993  pw->swipe_end_time);
2994  vlib_cli_output (vm, " sw_if_index serviced bitmap: %U",
2996  vlib_cli_output (vm, " pending clear intfc bitmap : %U",
2999  vlib_cli_output (vm, " clear in progress: %u", pw->clear_in_process);
3000  vlib_cli_output (vm, " interrupt is pending: %d",
3001  pw->interrupt_is_pending);
3002  vlib_cli_output (vm, " interrupt is needed: %d",
3003  pw->interrupt_is_needed);
3004  vlib_cli_output (vm, " interrupt is unwanted: %d",
3005  pw->interrupt_is_unwanted);
3006  vlib_cli_output (vm, " interrupt generation: %d",
3007  pw->interrupt_generation);
3008  }
3009  vlib_cli_output (vm, "\n\nConn cleaner thread counters:");
3010 #define _(cnt, desc) vlib_cli_output(vm, " %20lu: %s", am->cnt, desc);
3012 #undef _
3013  vlib_cli_output (vm, "Interrupt generation: %d",
3015  vlib_cli_output (vm,
3016  "Sessions per interval: min %lu max %lu increment: %f ms current: %f ms",
3019  am->fa_cleaner_wait_time_increment * 1000.0,
3021  1000.0 / (f64) vm->clib_time.clocks_per_second);
3022 }
3023 
3024 static clib_error_t *
3026  unformat_input_t * input,
3027  vlib_cli_command_t * cmd)
3028 {
3029  clib_error_t *error = 0;
3030  acl_main_t *am = &acl_main;
3031 
3032  u32 show_bihash_verbose = 0;
3033  u32 show_session_thread_id = ~0;
3034  u32 show_session_session_index = ~0;
3035  (void) unformat (input, "thread %u index %u", &show_session_thread_id,
3036  &show_session_session_index);
3037  (void) unformat (input, "verbose %u", &show_bihash_verbose);
3038 
3039  acl_plugin_show_sessions (am, show_session_thread_id,
3040  show_session_session_index);
3041  show_fa_sessions_hash (vm, show_bihash_verbose);
3042  return error;
3043 }
3044 
3045 static void
3047 {
3048  vlib_main_t *vm = am->vlib_main;
3049  ace_mask_type_entry_t *mte;
3050 
3051  vlib_cli_output (vm, "Mask-type entries:");
3052  /* *INDENT-OFF* */
3054  ({
3055  vlib_cli_output(vm, " %3d: %016llx %016llx %016llx %016llx %016llx %016llx refcount %d",
3056  mte - am->ace_mask_type_pool,
3057  mte->mask.kv.key[0], mte->mask.kv.key[1], mte->mask.kv.key[2],
3058  mte->mask.kv.key[3], mte->mask.kv.key[4], mte->mask.kv.value, mte->refcount);
3059  }));
3060  /* *INDENT-ON* */
3061 }
3062 
3063 static void
3065 {
3066  vlib_main_t *vm = am->vlib_main;
3067  u32 i, j;
3068  u64 *m;
3069  vlib_cli_output (vm, "Mask-ready ACL representations\n");
3070  for (i = 0; i < vec_len (am->hash_acl_infos); i++)
3071  {
3072  if ((acl_index != ~0) && (acl_index != i))
3073  {
3074  continue;
3075  }
3076  hash_acl_info_t *ha = &am->hash_acl_infos[i];
3077  vlib_cli_output (vm, "acl-index %u bitmask-ready layout\n", i);
3078  vlib_cli_output (vm, " applied inbound on sw_if_index list: %U\n",
3080  vlib_cli_output (vm, " applied outbound on sw_if_index list: %U\n",
3082  vlib_cli_output (vm, " mask type index bitmap: %U\n",
3084  for (j = 0; j < vec_len (ha->rules); j++)
3085  {
3086  hash_ace_info_t *pa = &ha->rules[j];
3087  m = (u64 *) & pa->match;
3088  vlib_cli_output (vm,
3089  " %4d: %016llx %016llx %016llx %016llx %016llx %016llx mask index %d acl %d rule %d action %d src/dst portrange not ^2: %d,%d\n",
3090  j, m[0], m[1], m[2], m[3], m[4], m[5],
3091  pa->mask_type_index, pa->acl_index, pa->ace_index,
3094  }
3095  }
3096 }
3097 
3098 static void
3100 {
3101  vlib_cli_output (vm,
3102  " %4d: acl %d rule %d action %d bitmask-ready rule %d next %d prev %d tail %d hitcount %lld",
3103  j, pae->acl_index, pae->ace_index, pae->action,
3106  pae->tail_applied_entry_index, pae->hitcount);
3107 }
3108 
3109 static void
3111 {
3112  vlib_main_t *vm = am->vlib_main;
3113  u32 swi, j;
3114  vlib_cli_output (vm, "Applied lookup entries for interfaces");
3115 
3116  for (swi = 0;
3120  || (swi < vec_len (am->output_hash_entry_vec_by_sw_if_index)); swi++)
3121  {
3122  if ((sw_if_index != ~0) && (sw_if_index != swi))
3123  {
3124  continue;
3125  }
3126  vlib_cli_output (vm, "sw_if_index %d:", swi);
3128  {
3131  vlib_cli_output (vm, " input lookup mask_type_index_bitmap: %U",
3133  vlib_cli_output (vm, " input applied acls: %U", format_vec32,
3134  pal->applied_acls, "%d");
3135  }
3137  {
3138  vlib_cli_output (vm, " input lookup applied entries:");
3139  for (j = 0;
3141  j++)
3142  {
3143  acl_plugin_print_pae (vm, j,
3145  [swi][j]);
3146  }
3147  }
3148 
3150  {
3153  vlib_cli_output (vm, " output lookup mask_type_index_bitmap: %U",
3155  vlib_cli_output (vm, " output applied acls: %U", format_vec32,
3156  pal->applied_acls, "%d");
3157  }
3159  {
3160  vlib_cli_output (vm, " output lookup applied entries:");
3161  for (j = 0;
3163  j++)
3164  {
3165  acl_plugin_print_pae (vm, j,
3167  [swi][j]);
3168  }
3169  }
3170  }
3171 }
3172 
3173 static void
3174 acl_plugin_show_tables_bihash (acl_main_t * am, u32 show_bihash_verbose)
3175 {
3176  vlib_main_t *vm = am->vlib_main;
3177  show_hash_acl_hash (vm, am, show_bihash_verbose);
3178 }
3179 
3180 static clib_error_t *
3182  unformat_input_t * input,
3183  vlib_cli_command_t * cmd)
3184 {
3185  clib_error_t *error = 0;
3186  acl_main_t *am = &acl_main;
3187 
3188  u32 acl_index = ~0;
3189  u32 sw_if_index = ~0;
3190  int show_acl_hash_info = 0;
3191  int show_applied_info = 0;
3192  int show_mask_type = 0;
3193  int show_bihash = 0;
3194  u32 show_bihash_verbose = 0;
3195 
3196  if (unformat (input, "acl"))
3197  {
3198  show_acl_hash_info = 1;
3199  /* mask-type is handy to see as well right there */
3200  show_mask_type = 1;
3201  unformat (input, "index %u", &acl_index);
3202  }
3203  else if (unformat (input, "applied"))
3204  {
3205  show_applied_info = 1;
3206  unformat (input, "sw_if_index %u", &sw_if_index);
3207  }
3208  else if (unformat (input, "mask"))
3209  {
3210  show_mask_type = 1;
3211  }
3212  else if (unformat (input, "hash"))
3213  {
3214  show_bihash = 1;
3215  unformat (input, "verbose %u", &show_bihash_verbose);
3216  }
3217 
3218  if (!
3219  (show_mask_type || show_acl_hash_info || show_applied_info
3220  || show_bihash))
3221  {
3222  /* if no qualifiers specified, show all */
3223  show_mask_type = 1;
3224  show_acl_hash_info = 1;
3225  show_applied_info = 1;
3226  show_bihash = 1;
3227  }
3228  if (show_mask_type)
3230  if (show_acl_hash_info)
3231  acl_plugin_show_tables_acl_hash_info (am, acl_index);
3232  if (show_applied_info)
3233  acl_plugin_show_tables_applied_info (am, sw_if_index);
3234  if (show_bihash)
3235  acl_plugin_show_tables_bihash (am, show_bihash_verbose);
3236 
3237  return error;
3238 }
3239 
3240 static clib_error_t *
3242  unformat_input_t * input, vlib_cli_command_t * cmd)
3243 {
3244  clib_error_t *error = 0;
3245  acl_main_t *am = &acl_main;
3248  return error;
3249 }
3250 
3251  /* *INDENT-OFF* */
3252 VLIB_CLI_COMMAND (aclplugin_set_command, static) = {
3253  .path = "set acl-plugin",
3254  .short_help = "set acl-plugin session timeout {{udp idle}|tcp {idle|transient}} <seconds>",
3255  .function = acl_set_aclplugin_fn,
3256 };
3257 
3258 VLIB_CLI_COMMAND (aclplugin_show_acl_command, static) = {
3259  .path = "show acl-plugin acl",
3260  .short_help = "show acl-plugin acl [index N]",
3261  .function = acl_show_aclplugin_acl_fn,
3262 };
3263 
3264 VLIB_CLI_COMMAND (aclplugin_show_decode_5tuple_command, static) = {
3265  .path = "show acl-plugin decode 5tuple",
3266  .short_help = "show acl-plugin decode 5tuple XXXX XXXX XXXX XXXX XXXX XXXX",
3268 };
3269 
3270 VLIB_CLI_COMMAND (aclplugin_show_interface_command, static) = {
3271  .path = "show acl-plugin interface",
3272  .short_help = "show acl-plugin interface [sw_if_index N] [acl]",
3273  .function = acl_show_aclplugin_interface_fn,
3274 };
3275 
3276 VLIB_CLI_COMMAND (aclplugin_show_memory_command, static) = {
3277  .path = "show acl-plugin memory",
3278  .short_help = "show acl-plugin memory",
3279  .function = acl_show_aclplugin_memory_fn,
3280 };
3281 
3282 VLIB_CLI_COMMAND (aclplugin_show_sessions_command, static) = {
3283  .path = "show acl-plugin sessions",
3284  .short_help = "show acl-plugin sessions",
3285  .function = acl_show_aclplugin_sessions_fn,
3286 };
3287 
3288 VLIB_CLI_COMMAND (aclplugin_show_tables_command, static) = {
3289  .path = "show acl-plugin tables",
3290  .short_help = "show acl-plugin tables [ acl [index N] | applied [ sw_if_index N ] | mask | hash [verbose N] ]",
3291  .function = acl_show_aclplugin_tables_fn,
3292 };
3293 
3294 VLIB_CLI_COMMAND (aclplugin_show_macip_acl_command, static) = {
3295  .path = "show acl-plugin macip acl",
3296  .short_help = "show acl-plugin macip acl",
3297  .function = acl_show_aclplugin_macip_acl_fn,
3298 };
3299 
3300 VLIB_CLI_COMMAND (aclplugin_show_macip_interface_command, static) = {
3301  .path = "show acl-plugin macip interface",
3302  .short_help = "show acl-plugin macip interface",
3304 };
3305 
3306 VLIB_CLI_COMMAND (aclplugin_clear_command, static) = {
3307  .path = "clear acl-plugin sessions",
3308  .short_help = "clear acl-plugin sessions",
3309  .function = acl_clear_aclplugin_fn,
3310 };
3311 /* *INDENT-ON* */
3312 
3313 static clib_error_t *
3315 {
3316  acl_main_t *am = &acl_main;
3317  u32 conn_table_hash_buckets;
3318  u32 conn_table_hash_memory_size;
3319  u32 conn_table_max_entries;
3320  u32 main_heap_size;
3321  u32 hash_heap_size;
3322  u32 hash_lookup_hash_buckets;
3323  u32 hash_lookup_hash_memory;
3324 
3325  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3326  {
3327  if (unformat
3328  (input, "connection hash buckets %d", &conn_table_hash_buckets))
3329  am->fa_conn_table_hash_num_buckets = conn_table_hash_buckets;
3330  else if (unformat (input, "connection hash memory %d",
3331  &conn_table_hash_memory_size))
3332  am->fa_conn_table_hash_memory_size = conn_table_hash_memory_size;
3333  else if (unformat (input, "connection count max %d",
3334  &conn_table_max_entries))
3335  am->fa_conn_table_max_entries = conn_table_max_entries;
3336  else if (unformat (input, "main heap size %d", &main_heap_size))
3337  am->acl_mheap_size = main_heap_size;
3338  else if (unformat (input, "hash lookup heap size %d", &hash_heap_size))
3339  am->hash_lookup_mheap_size = hash_heap_size;
3340  else if (unformat (input, "hash lookup hash buckets %d",
3341  &hash_lookup_hash_buckets))
3342  am->hash_lookup_hash_buckets = hash_lookup_hash_buckets;
3343  else if (unformat (input, "hash lookup hash memory %d",
3344  &hash_lookup_hash_memory))
3345  am->hash_lookup_hash_memory = hash_lookup_hash_memory;
3346  else
3347  return clib_error_return (0, "unknown input '%U'",
3348  format_unformat_error, input);
3349  }
3350  return 0;
3351 }
3352 
3353 VLIB_CONFIG_FUNCTION (acl_plugin_config, "acl-plugin");
3354 
3355 static clib_error_t *
3357 {
3358  acl_main_t *am = &acl_main;
3359  clib_error_t *error = 0;
3360  memset (am, 0, sizeof (*am));
3361  am->vlib_main = vm;
3362  am->vnet_main = vnet_get_main ();
3363 
3364  u8 *name = format (0, "acl_%08x%c", api_version, 0);
3365 
3366  /* Ask for a correctly-sized block of API message decode slots */
3367  am->msg_id_base = vl_msg_api_get_msg_ids ((char *) name,
3369 
3370  error = acl_plugin_api_hookup (vm);
3371 
3372  /* Add our API messages to the global name_crc hash table */
3374 
3375  vec_free (name);
3376 
3377  acl_setup_fa_nodes ();
3378 
3381 
3384 
3391 
3398  vec_validate (am->per_worker_data, tm->n_vlib_mains - 1);
3399  {
3400  u16 wk;
3401  u8 tt;
3402  for (wk = 0; wk < vec_len (am->per_worker_data); wk++)
3403  {
3407  for (tt = 0; tt < ACL_N_TIMEOUTS; tt++)
3408  {
3409  pw->fa_conn_list_head[tt] = ~0;
3410  pw->fa_conn_list_tail[tt] = ~0;
3411  }
3412  }
3413  }
3414 
3421 
3422  am->fa_cleaner_cnt_delete_by_sw_index = 0;
3423  am->fa_cleaner_cnt_delete_by_sw_index_ok = 0;
3424  am->fa_cleaner_cnt_unknown_event = 0;
3425  am->fa_cleaner_cnt_timer_restarted = 0;
3426  am->fa_cleaner_cnt_wait_with_timeout = 0;
3427 
3428 
3429 #define _(N, v, s) am->fa_ipv6_known_eh_bitmap = clib_bitmap_set(am->fa_ipv6_known_eh_bitmap, v, 1);
3431 #undef _
3433 
3434  /* use the new fancy hash-based matching */
3435  am->use_hash_acl_matching = 1;
3436 
3437  return error;
3438 }
3439 
3441 
3442 
3443 /*
3444  * fd.io coding-style-patch-verification: ON
3445  *
3446  * Local Variables:
3447  * eval: (c-set-style "gnu")
3448  * End:
3449  */
acl_rule_t * rules
Definition: acl.h:107
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:432
macip_acl_rule_t * rules
Definition: acl.h:114
u32 * acl_ip4_output_classify_table_by_sw_if_index
Definition: acl.h:179
static int macip_acl_interface_add_acl(acl_main_t *am, u32 sw_if_index, u32 macip_acl_index)
Definition: acl.c:1638
u8 src_mac[6]
Definition: acl.h:94
u32 fa_cleaner_node_index
Definition: acl.h:197
u32 session_timeout_sec[ACL_N_TIMEOUTS]
Definition: acl.h:199
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:212
static int macip_acl_interface_add_del_acl(u32 sw_if_index, u8 is_add, u32 acl_list_index)
Definition: acl.c:1700
static clib_error_t * acl_clear_aclplugin_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:3241
static int acl_set_skip_ipv6_eh(u32 eh, u32 value)
Definition: acl.c:2397
static int acl_hook_l2_output_classify(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:787
u16 vl_msg_api_get_msg_ids(const char *name, int n)
Definition: api_shared.c:872
static int verify_message_len(void *mp, u32 expected_len, char *where)
Definition: acl.c:1733
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:429
#define UDP_SESSION_IDLE_TIMEOUT_SEC
Definition: acl.h:36
void acl_plugin_hash_acl_set_trace_heap(acl_main_t *am, int on)
Definition: hash_lookup.c:290
static void send_macip_acl_details(acl_main_t *am, unix_shared_memory_queue_t *q, macip_acl_list_t *acl, u32 context)
Definition: acl.c:2116
u32 * acl_dot1ad_input_classify_table_by_sw_if_index
Definition: acl.h:183
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
static clib_error_t * acl_init(vlib_main_t *vm)
Definition: acl.c:3356
static void acl_setup_fa_nodes(void)
Definition: acl.c:2327
static void send_macip_acl_interface_list_details(acl_main_t *am, unix_shared_memory_queue_t *q, u32 sw_if_index, u32 acl_index, u32 context)
Definition: acl.c:2233
void show_fa_sessions_hash(vlib_main_t *vm, u32 verbose)
Definition: fa_node.c:1720
int acl_interface_out_enable_disable(acl_main_t *am, u32 sw_if_index, int enable_disable)
Definition: acl.c:919
u8 is_ipv6
Definition: acl.h:76
char ** l2output_get_feat_names(void)
Definition: l2_output.c:38
static int acl_interface_del_inout_acl(u32 sw_if_index, u8 is_input, u32 acl_list_index)
Definition: acl.c:1019
uword * pending_clear_sw_if_index_bitmap
Definition: fa_node.h:134
static void vl_api_acl_plugin_get_version_t_handler(vl_api_acl_plugin_get_version_t *mp)
Definition: acl.c:136
Definition: acl.h:125
a
Definition: bitmap.h:516
int acl_interface_in_enable_disable(acl_main_t *am, u32 sw_if_index, int enable_disable)
Definition: acl.c:894
u64 fa_current_cleaner_timer_wait_interval
Definition: acl.h:247
u32 acl_index
Set the vector of input/output ACLs checked for an interface.
Definition: acl.api:230
#define foreach_acl_plugin_api_msg
Definition: acl.c:63
u32 ** input_acl_vec_by_sw_if_index
Definition: acl.h:157
u16 msg_id_base
Definition: acl.h:137
Dump the list(s) of ACL applied to specific or all interfaces.
Definition: acl.api:281
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
vl_api_macip_acl_rule_t r[count]
Definition: acl.api:319
static void acl_plugin_print_pae(vlib_main_t *vm, int j, applied_hash_ace_entry_t *pae)
Definition: acl.c:3099
static int count_skip(u8 *p, u32 size)
Definition: acl.c:414
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:1750
static void vl_api_macip_acl_dump_t_handler(vl_api_macip_acl_dump_t *mp)
Definition: acl.c:2166
union fa_session_t::@311 tcp_flags_seen
int l4_match_nonfirst_fragment
Definition: acl.h:221
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:18
#define ACL_PLUGIN_VERSION_MINOR
Definition: acl.h:34
static clib_error_t * acl_plugin_config(vlib_main_t *vm, unformat_input_t *input)
Definition: acl.c:3314
#define ACL_PLUGIN_HASH_LOOKUP_HASH_MEMORY
Definition: acl.h:44
#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:2030
f64 clocks_per_second
Definition: time.h:53
u8 dst_prefixlen
Definition: acl.h:80
u8 action
u32 hash_ace_info_index
u32 * acl_ip6_input_classify_table_by_sw_if_index
Definition: acl.h:178
fa_5tuple_t info
Definition: fa_node.h:58
u32 count
Definition: acl.h:106
u32 l2_table_index
Definition: acl.h:118
void vnet_l2_input_classify_enable_disable(u32 sw_if_index, int enable_disable)
Enable/disable l2 input classification on a specific interface.
u8 dot1ad_5tuple_mask[]
Definition: acl.c:400
static mheap_t * mheap_header(u8 *v)
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
format_function_t format_ip46_address
Definition: format.h:61
u64 session_timeout[ACL_N_TIMEOUTS]
Definition: acl.h:255
fa_session_t * fa_sessions_pool
Definition: fa_node.h:108
u32 l2_input_classify_next_acl_ip4
Definition: acl.h:207
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
Access List Rule entry.
Definition: acl.api:88
applied_hash_acl_info_t * output_applied_hash_acl_info_by_sw_if_index
Definition: acl.h:152
clib_time_t clib_time
Definition: main.h:62
u32 dot1ad_table_index
Definition: acl.c:1202
u8 link_list_id
Definition: fa_node.h:69
u16 dstport_or_icmpcode_last
Definition: acl.api:113
#define MHEAP_FLAG_THREAD_SAFE
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:1206
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
Details about one MACIP ACL.
Definition: acl.api:419
u32 fa_acl_out_ip4_l2_node_feat_next_node_index[32]
Definition: acl.h:214
f64 fa_cleaner_wait_time_increment
Definition: acl.h:245
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:595
void hash_acl_add(acl_main_t *am, int acl_index)
Definition: hash_lookup.c:769
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:615
uword fa_conn_table_hash_memory_size
Definition: acl.h:225
u16 dst_port_or_code_last
Definition: acl.h:85
static clib_error_t * acl_sw_interface_add_del(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
Definition: acl.c:2413
u8 src_mac_mask[6]
Definition: acl.h:95
u32 l2_output_classify_next_acl_ip4
Definition: acl.h:209
u8 src_prefixlen
Definition: acl.h:78
ip46_address_t src_ip_addr
Definition: acl.h:96
void mv(vnet_classify_table_t *t)
Definition: vnet_classify.c:69
u32 next_applied_entry_index
void acl_plugin_hash_acl_set_validate_heap(acl_main_t *am, int on)
Definition: hash_lookup.c:275
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:438
u32 link_prev_idx
Definition: fa_node.h:67
#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:944
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:2761
u16 dstport_or_icmpcode_first
Definition: acl.api:112
u64 fa_conn_table_max_entries
Definition: acl.h:226
static void acl_plugin_show_interface(acl_main_t *am, u32 sw_if_index, int show_acl)
Definition: acl.c:2775
vnet_main_t * vnet_main
Definition: acl.h:275
unsigned long long u32x4
Definition: ixge.c:28
ip46_address_t src
Definition: acl.h:77
u8 src_ip_prefix_len
Definition: acl.api:93
u8 tcp_flags_value
Definition: acl.api:120
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 clib_error_t * acl_show_aclplugin_interface_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:2845
#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:97
u8 is_permit
Definition: acl.h:75
#define ACL_FA_CONN_TABLE_DEFAULT_MAX_ENTRIES
Definition: fa_node.h:20
static void acl_print_acl(vlib_main_t *vm, acl_main_t *am, int acl_index)
Definition: acl.c:2684
unsigned long u64
Definition: types.h:89
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:1196
#define vec_search(v, E)
Search a vector for the index of the entry that matches.
Definition: vec.h:937
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:2826
u32 ip4_table_index
Definition: acl.h:116
void hash_acl_unapply(acl_main_t *am, u32 sw_if_index, u8 is_input, int acl_index)
Definition: hash_lookup.c:523
u32 * inbound_sw_if_index_list
void * vl_msg_api_alloc(int nbytes)
Reply to add/replace MACIP ACL.
Definition: acl.api:360
u32 fa_acl_out_ip6_l2_node_feat_next_node_index[32]
Definition: acl.h:215
static u8 * my_macip_acl_rule_t_pretty_format(u8 *out, va_list *args)
Definition: acl.c:2612
u32 * acl_ip4_input_classify_table_by_sw_if_index
Definition: acl.h:177
#define fl(x, y)
ip46_address_t dst
Definition: acl.h:79
uword * mask_type_index_bitmap
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:484
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:2861
applied_hash_acl_info_t * input_applied_hash_acl_info_by_sw_if_index
Definition: acl.h:151
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:682
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:459
Details about a single MACIP ACL contents.
Definition: acl.api:472
static void acl_set_session_max_entries(u32 value)
Definition: acl.c:2390
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:2318
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:950
VLIB_PLUGIN_REGISTER()
#define ACL_FA_DEFAULT_CLEANER_WAIT_TIME_INCREMENT
Definition: acl.h:244
u16 dst_port_or_code_first
Definition: acl.h:84
u8 dot1q_5tuple_mask[]
Definition: acl.c:392
#define TCP_SESSION_IDLE_TIMEOUT_SEC
Definition: acl.h:37
static void vl_api_acl_dump_t_handler(vl_api_acl_dump_t *mp)
Definition: acl.c:1905
#define v
Definition: acl.c:341
static void acl_plugin_show_tables_applied_info(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:3110
struct _unformat_input_t unformat_input_t
uword * fa_ipv6_known_eh_bitmap
Definition: acl.h:218
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:241
hash_acl_info_t * hash_acl_infos
Definition: acl.h:140
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:271
void acl_plugin_acl_set_validate_heap(acl_main_t *am, int on)
Definition: acl.c:103
u64 hitcount
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:3181
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:119
hash_ace_info_t * rules
#define REPLY_MACRO(t)
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:801
vl_api_acl_rule_t r[count]
Definition: acl.api:167
static int get_l3_src_offset(int is6)
Definition: acl.c:1257
f64 seconds_per_clock
Definition: time.h:57
void show_hash_acl_hash(vlib_main_t *vm, acl_main_t *am, u32 verbose)
Definition: hash_lookup.c:889
u64 last_active_time
Definition: fa_node.h:59
static int macip_maybe_apply_unapply_classifier_tables(acl_main_t *am, u32 acl_index, int is_apply)
Definition: acl.c:1506
u32 l2_input_classify_next_acl_ip6
Definition: acl.h:208
u8 proto
Definition: acl.h:81
u8 dst_ip_addr[16]
Definition: acl.api:94
static u8 * my_format_mac_address(u8 *s, va_list *args)
Definition: acl.c:2604
static void send_acl_details(acl_main_t *am, unix_shared_memory_queue_t *q, acl_list_t *acl, u32 context)
Definition: acl.c:1874
u16 src_port_or_type_first
Definition: acl.h:82
u64 fa_min_deleted_sessions_per_interval
Definition: acl.h:242
static int match_type_compare(macip_match_type_t *m1, macip_match_type_t *m2)
Definition: acl.c:1249
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:198
static void acl_plugin_show_tables_acl_hash_info(acl_main_t *am, u32 acl_index)
Definition: acl.c:3064
#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
static int acl_unhook_l2_output_classify(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:549
Dump the list(s) of MACIP ACLs applied to specific or all interfaces.
Definition: acl.api:458
static int match_type_metric(macip_match_type_t *m)
Definition: acl.c:1228
static int macip_acl_del_list(u32 acl_list_index)
Definition: acl.c:1664
Dump one or all defined MACIP ACLs.
Definition: acl.api:404
api_main_t api_main
Definition: api_shared.c:35
#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:456
vlib_main_t * vm
Definition: buffer.c:283
vec_header_t h
Definition: buffer.c:282
static void acl_plugin_show_acl(acl_main_t *am, u32 acl_index)
Definition: acl.c:2727
applied_hash_ace_entry_t ** output_hash_entry_vec_by_sw_if_index
Definition: acl.h:150
u64 fa_session_total_adds
Definition: acl.h:201
#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:121
u32 dot1q_table_index
Definition: acl.c:1201
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:62
u32 * outbound_sw_if_index_list
static void * clib_mem_set_heap(void *heap)
Definition: mem.h:226
u16 srcport_or_icmptype_first
Definition: acl.api:110
#define PRINT_AND_RESET(vm, out0)
Definition: acl.c:2682
void hash_acl_delete(acl_main_t *am, int acl_index)
Definition: hash_lookup.c:826
Reply to add/replace ACL.
Definition: acl.api:176
#define clib_warning(format, args...)
Definition: error.h:59
static int acl_interface_add_inout_acl(u32 sw_if_index, u8 is_input, u32 acl_list_index)
Definition: acl.c:951
u64 memory_size
Definition: vhost-user.h:77
Definition: acl.h:73
Reply with the vector of MACIP ACLs by sw_if_index.
Definition: acl.api:445
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
u8 * format_vec32(u8 *s, va_list *va)
Definition: std-formats.c:43
u32 sw_if_index
Definition: fa_node.h:60
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:168
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:268
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
#define foreach_fa_cleaner_counter
Definition: acl.h:260
vl_api_macip_acl_rule_t r[count]
Definition: acl.api:351
void acl_fa_enable_disable(u32 sw_if_index, int is_input, int enable_disable)
Definition: fa_node.c:1665
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:93
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:73
u16 srcport_or_icmptype_last
Definition: acl.api:111
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:2654
#define ACL_PLUGIN_HASH_LOOKUP_HASH_BUCKETS
Definition: acl.h:43
u32 hash_lookup_hash_buckets
Definition: acl.h:142
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
static void vl_api_acl_interface_add_del_t_handler(vl_api_acl_interface_add_del_t *mp)
Definition: acl.c:1789
#define ASSERT(truth)
static int macip_acl_interface_del_acl(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:1613
unsigned int u32
Definition: types.h:88
u8 tag[64]
Definition: acl.h:105
static void vl_api_macip_acl_del_t_handler(vl_api_macip_acl_del_t *mp)
Definition: acl.c:2084
u16 src_port_or_type_last
Definition: acl.h:83
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:1268
static void acl_set_timeout_sec(int timeout_type, u32 value)
Definition: acl.c:2371
static void send_acl_interface_list_details(acl_main_t *am, unix_shared_memory_queue_t *q, u32 sw_if_index, u32 context)
Definition: acl.c:1948
u64 size
Definition: vhost-user.h:76
#define ACL_FA_DEFAULT_HEAP_SIZE
Definition: acl.h:40
#define MHEAP_FLAG_VALIDATE
u8 dst_ip_prefix_len
Definition: acl.api:95
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:2057
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:2296
static int macip_acl_add_list(u32 count, vl_api_macip_acl_rule_t rules[], u32 *acl_list_index, u8 *tag)
Definition: acl.c:1527
uword * serviced_sw_if_index_bitmap
Definition: fa_node.h:132
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:213
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:68
u64 uword
Definition: types.h:112
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.
ace_mask_type_entry_t * ace_mask_type_pool
Definition: acl.h:171
#define MHEAP_FLAG_SMALL_OBJECT_CACHE
static void macip_acl_print(acl_main_t *am, u32 macip_acl_index)
Definition: acl.c:2627
u32 prev_applied_entry_index
u32 * macip_acl_by_sw_if_index
Definition: acl.h:188
Get the vector of MACIP ACL IDs applied to the interfaces.
Definition: acl.api:433
#define XX
Definition: acl.c:338
u32 * acl_ip6_output_classify_table_by_sw_if_index
Definition: acl.h:180
static void vl_api_acl_interface_list_dump_t_handler(vl_api_acl_interface_list_dump_t *mp)
Definition: acl.c:1994
u16 as_u16
Definition: fa_node.h:63
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:177
unsigned short u16
Definition: types.h:57
static void vl_api_acl_del_t_handler(vl_api_acl_del_t *mp)
Definition: acl.c:1777
macip_acl_list_t * macip_acls
Definition: acl.h:154
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:3025
#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:117
static void vl_api_macip_acl_interface_list_dump_t_handler(vl_api_macip_acl_interface_list_dump_t *mp)
Definition: acl.c:2258
u8 tcp_flags_mask
Definition: acl.h:87
acl_fa_per_worker_data_t * per_worker_data
Definition: acl.h:252
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:956
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:663
int fa_interrupt_generation
Definition: acl.h:249
u32 ** input_sw_if_index_vec_by_acl
Definition: acl.h:161
void vnet_l2_output_classify_enable_disable(u32 sw_if_index, int enable_disable)
Enable/disable l2 input classification on a specific interface.
static void vl_api_acl_interface_set_acl_list_t_handler(vl_api_acl_interface_set_acl_list_t *mp)
Definition: acl.c:1809
u64 fa_max_deleted_sessions_per_interval
Definition: acl.h:234
void * acl_mheap
Definition: acl.h:133
static clib_error_t * acl_set_aclplugin_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:2439
u16 thread_index
Definition: fa_node.h:64
unformat_function_t unformat_memory_size
Definition: format.h:294
static void acl_interface_reset_inout_acls(u32 sw_if_index, u8 is_input)
Definition: acl.c:1100
void hash_acl_apply(acl_main_t *am, u32 sw_if_index, u8 is_input, int acl_index)
Definition: hash_lookup.c:302
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:1169
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
u8 tcp_flags_value
Definition: acl.h:86
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:2890
static void copy_acl_rule_to_api_rule(vl_api_acl_rule_t *api_rule, acl_rule_t *r)
Definition: acl.c:1848
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:90
void * hash_lookup_mheap
Definition: acl.h:146
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: input_acl.c:59
u32 acl_mheap_size
Definition: acl.h:134
u32 tail_applied_entry_index
Add a MACIP ACL.
Definition: acl.api:313
u32 vl_msg_api_get_msg_length(void *msg_arg)
Definition: api_shared.c:634
u32 client_index
Definition: acl.api:253
u32 ** output_sw_if_index_vec_by_acl
Definition: acl.h:162
#define ACL_PLUGIN_VERSION_MAJOR
Definition: acl.h:33
u8 tag[64]
Definition: acl.h:112
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:2667
u32 * acl_dot1q_output_classify_table_by_sw_if_index
Definition: acl.h:184
#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:481
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
#define ACL_PLUGIN_HASH_LOOKUP_HEAP_SIZE
Definition: acl.h:42
u32 hash_lookup_mheap_size
Definition: acl.h:147
u32 l2_output_classify_next_acl_ip6
Definition: acl.h:210
u8 ip6_5tuple_mask[]
Definition: acl.c:372
static void acl_plugin_show_tables_mask_type(acl_main_t *am)
Definition: acl.c:3046
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:233
static void vl_api_acl_plugin_control_ping_t_handler(vl_api_acl_plugin_control_ping_t *mp)
Definition: acl.c:161
acl_list_t * acls
Definition: acl.h:139
u32 ** output_acl_vec_by_sw_if_index
Definition: acl.h:158
#define TCP_SESSION_TRANSIENT_TIMEOUT_SEC
Definition: acl.h:38
u8 is_permit
Definition: acl.h:92
static void vl_api_macip_acl_interface_add_del_t_handler(vl_api_macip_acl_interface_add_del_t *mp)
Definition: acl.c:2097
u32 hash_lookup_hash_memory
Definition: acl.h:143
u32 ace_index
u32 arp_table_index
Definition: acl.c:1200
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
u64 link_enqueue_time
Definition: fa_node.h:66
u32 fa_conn_table_hash_num_buckets
Definition: acl.h:224
u32 * acl_dot1q_input_classify_table_by_sw_if_index
Definition: acl.h:182
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:19
u64 fa_session_total_dels
Definition: acl.h:202
struct _unix_shared_memory_queue unix_shared_memory_queue_t
static int acl_del_list(u32 acl_list_index)
Definition: acl.c:263
static void macip_destroy_classify_tables(acl_main_t *am, u32 macip_acl_index)
Definition: acl.c:1480
static void vl_api_macip_acl_interface_get_t_handler(vl_api_macip_acl_interface_get_t *mp)
Definition: acl.c:2202
applied_hash_ace_entry_t ** input_hash_entry_vec_by_sw_if_index
Definition: acl.h:149
u8 ip4_5tuple_mask[]
Definition: acl.c:344
static void acl_plugin_show_tables_bihash(acl_main_t *am, u32 show_bihash_verbose)
Definition: acl.c:3174
foreach_fa_cleaner_counter vlib_main_t * vlib_main
Definition: acl.h:274
u32 * acl_dot1ad_output_classify_table_by_sw_if_index
Definition: acl.h:185